mirror of
https://github.com/zulip/zulip.git
synced 2025-11-07 07:23:22 +00:00
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:
committed by
Tim Abbott
parent
e87f2ff408
commit
c526543498
1
web/shared/icons/topic.svg
Normal file
1
web/shared/icons/topic.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" viewBox="0 0 16 16"><path fill="#000" fill-rule="evenodd" d="M2.86 1.31c-.83 0-1.52.68-1.52 1.52v7.63c0 .84.69 1.52 1.52 1.52h.2v2.3a.66.66 0 0 0 1.08.51L7.59 12h5.55c.83 0 1.52-.7 1.52-1.53V2.83c0-.84-.69-1.52-1.52-1.52H2.86Zm-.19 3.08V2.83c0-.1.09-.19.2-.19h10.27c.1 0 .19.09.19.2v1.55H2.67Zm10.66 1.33H2.67v4.74c0 .1.09.2.2.2h1.52v2.22l2.72-2.23h6.03a.2.2 0 0 0 .19-.19V5.72Z" clip-rule="evenodd"/></svg>
|
||||||
|
After Width: | Height: | Size: 482 B |
@@ -1,8 +1,6 @@
|
|||||||
import * as message_lists from "./message_lists";
|
import * as message_lists from "./message_lists";
|
||||||
import * as overlays from "./overlays";
|
|
||||||
import * as popover_menus from "./popover_menus";
|
import * as popover_menus from "./popover_menus";
|
||||||
import * as recent_topics_ui from "./recent_topics_ui";
|
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 stream_list from "./stream_list";
|
||||||
import * as sub_store from "./sub_store";
|
import * as sub_store from "./sub_store";
|
||||||
import * as unread_ui from "./unread_ui";
|
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) {
|
if (message_lists.current !== message_lists.home) {
|
||||||
message_lists.home.update_muting_and_rerender();
|
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(
|
recent_topics_ui.update_topic_visibility_policy(
|
||||||
user_topic_event.stream_id,
|
user_topic_event.stream_id,
|
||||||
user_topic_event.topic_name,
|
user_topic_event.topic_name,
|
||||||
|
|||||||
@@ -867,3 +867,18 @@ export const system_user_groups_list = [
|
|||||||
display_name: $t({defaultMessage: "Nobody"}),
|
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"}),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|||||||
@@ -3,22 +3,35 @@ import $ from "jquery";
|
|||||||
import render_user_topic_ui_row from "../templates/user_topic_ui_row.hbs";
|
import render_user_topic_ui_row from "../templates/user_topic_ui_row.hbs";
|
||||||
|
|
||||||
import * as ListWidget from "./list_widget";
|
import * as ListWidget from "./list_widget";
|
||||||
|
import * as settings_config from "./settings_config";
|
||||||
import * as ui from "./ui";
|
import * as ui from "./ui";
|
||||||
import * as user_topics from "./user_topics";
|
import * as user_topics from "./user_topics";
|
||||||
|
|
||||||
export let loaded = false;
|
export let loaded = false;
|
||||||
|
|
||||||
export function populate_list() {
|
export function populate_list() {
|
||||||
const all_muted_topics = user_topics.get_user_topics_for_visibility_policy(
|
const all_user_topics = [];
|
||||||
user_topics.all_visibility_policies.MUTED,
|
const visibility_policies = Object.values(user_topics.all_visibility_policies);
|
||||||
);
|
for (const visibility_policy of visibility_policies) {
|
||||||
const $muted_topics_table = $("#muted_topics_table");
|
/* For visibility_policy=INHERIT, 'get_user_topics_for_visibility_policy' returns
|
||||||
const $search_input = $("#muted_topics_search");
|
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, {
|
ListWidget.create($user_topics_table, all_user_topics, {
|
||||||
name: "muted-topics-list",
|
name: "user-topics-list",
|
||||||
modifier(user_topic) {
|
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: {
|
filter: {
|
||||||
$element: $search_input,
|
$element: $search_input,
|
||||||
@@ -26,28 +39,28 @@ export function populate_list() {
|
|||||||
return item.topic.toLocaleLowerCase().includes(value);
|
return item.topic.toLocaleLowerCase().includes(value);
|
||||||
},
|
},
|
||||||
onupdate() {
|
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"),
|
init_sort: ["numeric", "date_updated"],
|
||||||
$simplebar_container: $("#muted-topic-settings .progressive-table-wrapper"),
|
initially_descending_sort: true,
|
||||||
|
$parent_container: $("#user-topic-settings"),
|
||||||
|
$simplebar_container: $("#user-topic-settings .progressive-table-wrapper"),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function set_up() {
|
export function set_up() {
|
||||||
loaded = true;
|
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 $row = $(this).closest("tr");
|
||||||
const stream_id = Number.parseInt($row.attr("data-stream-id"), 10);
|
const stream_id = Number.parseInt($row.attr("data-stream-id"), 10);
|
||||||
const topic = $row.attr("data-topic");
|
const topic = $row.attr("data-topic");
|
||||||
|
const visibility_policy = this.value;
|
||||||
|
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
user_topics.set_user_topic_visibility_policy(
|
user_topics.set_user_topic_visibility_policy(stream_id, topic, visibility_policy);
|
||||||
stream_id,
|
|
||||||
topic,
|
|
||||||
user_topics.all_visibility_policies.INHERIT,
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
populate_list();
|
populate_list();
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ export function initialize() {
|
|||||||
load_func_dict.set("your-bots", settings_bots.set_up);
|
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("alert-words", alert_words_ui.set_up_alert_words);
|
||||||
load_func_dict.set("uploaded-files", attachments_ui.set_up_attachments);
|
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);
|
load_func_dict.set("muted-users", settings_muted_users.set_up);
|
||||||
|
|
||||||
// org
|
// org
|
||||||
|
|||||||
@@ -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;
|
padding: 4px 6px;
|
||||||
color: hsl(0deg 0% 33%);
|
color: hsl(0deg 0% 33%);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
|||||||
@@ -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">
|
<div class="settings_panel_list_header">
|
||||||
<h3>{{t "Muted topics"}}</h3>
|
<h3>{{t "Topic settings"}}</h3>
|
||||||
<input id="muted_topics_search" class="search" type="text" placeholder="{{t 'Filter muted topics' }}" aria-label="{{t 'Filter muted topics' }}"/>
|
<input id="user_topics_search" class="search" type="text" placeholder="{{t 'Filter topics' }}" aria-label="{{t 'Filter topics' }}"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="progressive-table-wrapper" data-simplebar>
|
<div class="progressive-table-wrapper" data-simplebar>
|
||||||
<table class="table table-condensed table-striped wrapped-table">
|
<table class="table table-condensed table-striped wrapped-table">
|
||||||
<thead class="table-sticky-headers">
|
<thead class="table-sticky-headers">
|
||||||
<th data-sort="alphabetic" data-sort-prop="stream">{{t "Stream" }}</th>
|
<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="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 data-sort="numeric" data-sort-prop="visibility_policy">{{t "Status" }}</th>
|
||||||
<th class="actions">{{t "Actions" }}</th>
|
<th data-sort="numeric" data-sort-prop="date_updated" class="active topic_date_updated">{{t "Date updated" }}</th>
|
||||||
</thead>
|
</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>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -44,9 +44,9 @@
|
|||||||
<div class="text">{{t "Uploaded files" }}</div>
|
<div class="text">{{t "Uploaded files" }}</div>
|
||||||
</li>
|
</li>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<li tabindex="0" data-section="muted-topics">
|
<li tabindex="0" data-section="topics">
|
||||||
<i class="icon zulip-icon zulip-icon-mute" aria-hidden="true"></i>
|
<i class="icon zulip-icon zulip-icon-topic" aria-hidden="true"></i>
|
||||||
<div class="text">{{t "Muted topics" }}</div>
|
<div class="text">{{t "Topics" }}</div>
|
||||||
</li>
|
</li>
|
||||||
<li tabindex="0" data-section="muted-users">
|
<li tabindex="0" data-section="muted-users">
|
||||||
<i class="icon fa fa-eye-slash" aria-hidden="true"></i>
|
<i class="icon fa fa-eye-slash" aria-hidden="true"></i>
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
{{#with user_topic}}
|
{{#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>{{stream}}</td>
|
||||||
<td>{{topic}}</td>
|
<td>{{topic}}</td>
|
||||||
<td class="topic_date_updated">{{date_updated_str}}</td>
|
<td>
|
||||||
<td class="actions">
|
<select class="settings_user_topic_visibility_policy prop-element list_select bootstrap-focus-style" data-setting-widget-type="number">
|
||||||
<span><a class="settings-unmute-topic">{{t "Unmute" }}</a></span>
|
{{#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>
|
||||||
|
<td class="topic_date_updated">{{date_updated_str}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{/with}}
|
{{/with}}
|
||||||
|
|||||||
@@ -49,14 +49,17 @@ run_test("settings", ({override}) => {
|
|||||||
assert.equal(settings_muted_topics.loaded, true);
|
assert.equal(settings_muted_topics.loaded, true);
|
||||||
assert.ok(populate_list_called);
|
assert.ok(populate_list_called);
|
||||||
|
|
||||||
const topic_click_handler = $("body").get_on_handler("click", ".settings-unmute-topic");
|
const topic_change_handler = $("body").get_on_handler(
|
||||||
assert.equal(typeof topic_click_handler, "function");
|
"change",
|
||||||
|
".settings_user_topic_visibility_policy",
|
||||||
|
);
|
||||||
|
assert.equal(typeof topic_change_handler, "function");
|
||||||
|
|
||||||
const event = {
|
const event = {
|
||||||
stopPropagation: noop,
|
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"]');
|
const $topic_tr_html = $('tr[data-topic="js"]');
|
||||||
$topic_fake_this.closest = (opts) => {
|
$topic_fake_this.closest = (opts) => {
|
||||||
assert.equal(opts, "tr");
|
assert.equal(opts, "tr");
|
||||||
@@ -77,13 +80,15 @@ run_test("settings", ({override}) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let unmute_topic_called = false;
|
let user_topic_visibility_policy_changed = false;
|
||||||
user_topics.set_user_topic_visibility_policy = (stream_id, topic) => {
|
user_topics.set_user_topic_visibility_policy = (stream_id, topic, visibility_policy) => {
|
||||||
assert.equal(stream_id, frontend.stream_id);
|
assert.equal(stream_id, frontend.stream_id);
|
||||||
assert.equal(topic, "js");
|
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);
|
$topic_fake_this.value = user_topics.all_visibility_policies.UNMUTED;
|
||||||
assert.ok(unmute_topic_called);
|
topic_change_handler.call($topic_fake_this, event);
|
||||||
|
assert.ok(user_topic_visibility_policy_changed);
|
||||||
assert.equal(topic_data_called, 2);
|
assert.equal(topic_data_called, 2);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user