mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	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:
		
				
					committed by
					
						
						Tim Abbott
					
				
			
			
				
	
			
			
			
						parent
						
							e56db79af4
						
					
				
				
					commit
					bbbaa109ec
				
			
							
								
								
									
										71
									
								
								frontend_tests/node_tests/settings_muted_users.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								frontend_tests/node_tests/settings_muted_users.js
									
									
									
									
									
										Normal 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);
 | 
			
		||||
});
 | 
			
		||||
@@ -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();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										56
									
								
								static/js/settings_muted_users.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								static/js/settings_muted_users.js
									
									
									
									
									
										Normal 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;
 | 
			
		||||
}
 | 
			
		||||
@@ -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()
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										9
									
								
								static/templates/muted_user_ui_row.hbs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								static/templates/muted_user_ui_row.hbs
									
									
									
									
									
										Normal 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}}
 | 
			
		||||
							
								
								
									
										13
									
								
								static/templates/settings/muted_users_settings.hbs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								static/templates/settings/muted_users_settings.hbs
									
									
									
									
									
										Normal 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>
 | 
			
		||||
@@ -12,4 +12,6 @@
 | 
			
		||||
    {{> settings/attachments_settings }}
 | 
			
		||||
 | 
			
		||||
    {{> settings/muted_topics_settings }}
 | 
			
		||||
 | 
			
		||||
    {{> settings/muted_users_settings }}
 | 
			
		||||
</div>
 | 
			
		||||
 
 | 
			
		||||
@@ -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">
 | 
			
		||||
 
 | 
			
		||||
@@ -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",
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user