settings: Add UI page for managing muted users.

This page is temporarily hidden except in the development environment,
because the "muted users" feature is incomplete.
This commit is contained in:
Abhijeet Prasad Bodas 2021-04-17 10:52:25 +05:30 committed by Tim Abbott
parent e56db79af4
commit bbbaa109ec
9 changed files with 169 additions and 0 deletions

View File

@ -0,0 +1,71 @@
"use strict";
const {strict: assert} = require("assert");
const {mock_cjs, mock_esm, zrequire} = require("../zjsunit/namespace");
const {run_test} = require("../zjsunit/test");
const $ = require("../zjsunit/zjquery");
mock_cjs("jquery", $);
const muting_ui = mock_esm("../../static/js/muting_ui");
const settings_muted_users = zrequire("settings_muted_users");
const muting = zrequire("muting");
const noop = () => {};
run_test("settings", (override) => {
muting.add_muted_user(5, 1577836800);
let populate_list_called = false;
override(settings_muted_users, "populate_list", () => {
const opts = muting.get_muted_users();
assert.deepEqual(opts, [
{
date_muted: 1577836800000,
date_muted_str: "Jan\u00A001,\u00A02020",
id: 5,
},
]);
populate_list_called = true;
});
settings_muted_users.reset();
assert.equal(settings_muted_users.loaded, false);
settings_muted_users.set_up();
assert.equal(settings_muted_users.loaded, true);
assert(populate_list_called);
const unmute_click_handler = $("body").get_on_handler("click", ".settings-unmute-user");
assert.equal(typeof unmute_click_handler, "function");
const event = {
stopPropagation: noop,
};
const unmute_button = $.create("settings-unmute-user");
const fake_row = $('tr[data-user-id="5"]');
unmute_button.closest = (opts) => {
assert.equal(opts, "tr");
return fake_row;
};
let row_attribute_fetched = false;
fake_row.attr = (opts) => {
if (opts === "data-user-id") {
row_attribute_fetched += 1;
return "5";
}
throw new Error(`Unknown attribute ${opts}`);
};
let unmute_user_called = false;
muting_ui.unmute_user = (user_id) => {
assert.equal(user_id, 5);
unmute_user_called = true;
};
unmute_click_handler.call(unmute_button, event);
assert(unmute_user_called);
assert(row_attribute_fetched);
});

View File

@ -16,6 +16,7 @@ import * as people from "./people";
import * as popovers from "./popovers";
import * as recent_topics from "./recent_topics";
import * as settings_muted_topics from "./settings_muted_topics";
import * as settings_muted_users from "./settings_muted_users";
import * as stream_data from "./stream_data";
import * as stream_list from "./stream_list";
import * as stream_popover from "./stream_popover";
@ -195,7 +196,14 @@ export function unmute_user(user_id) {
});
}
export function rerender_for_muted_user() {
if (overlays.settings_open() && settings_muted_users.loaded) {
settings_muted_users.populate_list();
}
}
export function handle_user_updates(muted_user_ids) {
popovers.hide_all();
muting.set_muted_users(muted_user_ids);
rerender_for_muted_user();
}

View File

@ -0,0 +1,56 @@
import $ from "jquery";
import render_muted_user_ui_row from "../templates/muted_user_ui_row.hbs";
import * as ListWidget from "./list_widget";
import * as muting from "./muting";
import * as muting_ui from "./muting_ui";
import * as people from "./people";
import * as ui from "./ui";
export let loaded = false;
export function populate_list() {
const muted_users = muting.get_muted_users().map((user) => ({
user_id: user.id,
user_name: people.get_full_name(user.id),
date_muted_str: user.date_muted_str,
}));
const muted_users_table = $("#muted_users_table");
const $search_input = $("#muted_users_search");
ListWidget.create(muted_users_table, muted_users, {
name: "muted-users-list",
modifier(muted_users) {
return render_muted_user_ui_row({muted_users});
},
filter: {
element: $search_input,
predicate(item, value) {
return item.user_name.toLocaleLowerCase().includes(value);
},
onupdate() {
ui.reset_scrollbar(muted_users_table.closest(".progressive-table-wrapper"));
},
},
parent_container: $("#muted-user-settings"),
simplebar_container: $("#muted-user-settings .progressive-table-wrapper"),
});
}
export function set_up() {
loaded = true;
$("body").on("click", ".settings-unmute-user", function (e) {
const $row = $(this).closest("tr");
const user_id = Number.parseInt($row.attr("data-user-id"), 10);
e.stopPropagation();
muting_ui.unmute_user(user_id);
});
populate_list();
}
export function reset() {
loaded = false;
}

View File

@ -9,6 +9,7 @@ import * as settings_exports from "./settings_exports";
import * as settings_invites from "./settings_invites";
import * as settings_linkifiers from "./settings_linkifiers";
import * as settings_muted_topics from "./settings_muted_topics";
import * as settings_muted_users from "./settings_muted_users";
import * as settings_notifications from "./settings_notifications";
import * as settings_org from "./settings_org";
import * as settings_playgrounds from "./settings_playgrounds";
@ -51,6 +52,7 @@ export function initialize() {
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("muted-users", settings_muted_users.set_up);
// org
load_func_dict.set("org_misc", settings_org.set_up);
@ -99,5 +101,6 @@ export function reset_sections() {
settings_streams.reset();
settings_user_groups.reset();
settings_muted_topics.reset();
settings_muted_users.reset();
// settings_users doesn't need a reset()
}

View File

@ -0,0 +1,9 @@
{{#with muted_users}}
<tr data-user-id="{{user_id}}" data-user-name="{{user_name}}" data-date-muted="{{date_muted_str}}">
<td>{{user_name}}</td>
<td>{{date_muted_str}}</td>
<td class="actions">
<span><a class="settings-unmute-user">{{t "Unmute" }}</a></span>
</td>
</tr>
{{/with}}

View File

@ -0,0 +1,13 @@
<div id="muted-user-settings" class="settings-section" data-name="muted-users">
<input id="muted_users_search" class="search" type="text" placeholder="{{t 'Filter muted users' }}" aria-label="{{t 'Filter muted users' }}"/>
<div class="progressive-table-wrapper" data-simplebar data-list-widget="muted-users-list">
<table class="table table-condensed table-striped wrapped-table">
<thead>
<th data-sort="alphabetic" data-sort-prop="user_name">{{t "User" }}</th>
<th data-sort="numeric" data-sort-prop="date_muted">{{t "Date muted" }}</th>
<th class="actions">{{t "Actions" }}</th>
</thead>
<tbody id="muted_users_table" class="required-text" data-empty="{{t 'You have not muted any users yet.'}}" data-list-widget="muted-users-list"></tbody>
</table>
</div>
</div>

View File

@ -12,4 +12,6 @@
{{> settings/attachments_settings }}
{{> settings/muted_topics_settings }}
{{> settings/muted_users_settings }}
</div>

View File

@ -43,6 +43,12 @@
<i class="icon fa fa-bell-slash" aria-hidden="true"></i>
<div class="text">{{ _('Muted topics') }}</div>
</li>
{% if development_environment %}
<li tabindex="0" data-section="muted-users">
<i class="icon fa fa-eye-slash" aria-hidden="true"></i>
<div class="text">{{ _('Muted users') }}</div>
</li>
{% endif %}
</ul>
<ul class="org-settings-list">

View File

@ -125,6 +125,7 @@ EXEMPT_FILES = {
"static/js/settings.js",
"static/js/settings_linkifiers.js",
"static/js/settings_playgrounds.js",
"static/js/settings_muted_users.js",
"static/js/settings_notifications.js",
"static/js/settings_org.js",
"static/js/settings_panel_menu.js",