mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-03 21:43:21 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			304 lines
		
	
	
		
			9.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			304 lines
		
	
	
		
			9.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
import $ from "jquery";
 | 
						|
 | 
						|
import render_leave_user_group_modal from "../templates/confirm_dialog/confirm_unsubscribe_private_stream.hbs";
 | 
						|
import render_user_group_member_list_entry from "../templates/stream_settings/stream_member_list_entry.hbs";
 | 
						|
import render_user_group_subscription_request_result from "../templates/stream_settings/stream_subscription_request_result.hbs";
 | 
						|
 | 
						|
import * as add_subscribers_pill from "./add_subscribers_pill";
 | 
						|
import * as blueslip from "./blueslip";
 | 
						|
import * as channel from "./channel";
 | 
						|
import * as confirm_dialog from "./confirm_dialog";
 | 
						|
import {$t, $t_html} from "./i18n";
 | 
						|
import * as ListWidget from "./list_widget";
 | 
						|
import {page_params} from "./page_params";
 | 
						|
import * as people from "./people";
 | 
						|
import * as settings_data from "./settings_data";
 | 
						|
import * as ui from "./ui";
 | 
						|
import * as user_group_edit from "./user_group_edit";
 | 
						|
import * as user_groups from "./user_groups";
 | 
						|
 | 
						|
export let pill_widget;
 | 
						|
let current_group_id;
 | 
						|
 | 
						|
function get_potential_members() {
 | 
						|
    const group = user_groups.get_user_group_from_id(current_group_id);
 | 
						|
    function is_potential_member(person) {
 | 
						|
        // user  verbose style filter to have room
 | 
						|
        // to add more potential checks easily.
 | 
						|
        if (group.members.has(person.user_id)) {
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
 | 
						|
    return people.filter_all_users(is_potential_member);
 | 
						|
}
 | 
						|
 | 
						|
function format_member_list_elem(person) {
 | 
						|
    return render_user_group_member_list_entry({
 | 
						|
        name: person.full_name,
 | 
						|
        user_id: person.user_id,
 | 
						|
        is_current_user: person.user_id === page_params.user_id,
 | 
						|
        email: settings_data.email_for_user_settings(person),
 | 
						|
        can_edit_subscribers: user_group_edit.can_edit(current_group_id),
 | 
						|
        show_email: settings_data.show_email(),
 | 
						|
    });
 | 
						|
}
 | 
						|
 | 
						|
function make_list_widget({$parent_container, name, user_ids}) {
 | 
						|
    const users = people.get_users_from_ids(user_ids);
 | 
						|
    people.sort_but_pin_current_user_on_top(users);
 | 
						|
 | 
						|
    const $list_container = $parent_container.find(".member_table");
 | 
						|
    $list_container.empty();
 | 
						|
 | 
						|
    const $simplebar_container = $parent_container.find(".member_list_container");
 | 
						|
 | 
						|
    return ListWidget.create($list_container, users, {
 | 
						|
        name,
 | 
						|
        modifier(item) {
 | 
						|
            return format_member_list_elem(item);
 | 
						|
        },
 | 
						|
        filter: {
 | 
						|
            $element: $parent_container.find(".search"),
 | 
						|
            predicate(person, value) {
 | 
						|
                const matcher = people.build_person_matcher(value);
 | 
						|
                const match = matcher(person);
 | 
						|
 | 
						|
                return match;
 | 
						|
            },
 | 
						|
        },
 | 
						|
        $simplebar_container,
 | 
						|
    });
 | 
						|
}
 | 
						|
 | 
						|
export function enable_member_management({group, $parent_container}) {
 | 
						|
    const group_id = group.id;
 | 
						|
 | 
						|
    const $pill_container = $parent_container.find(".pill-container");
 | 
						|
 | 
						|
    // current_group_id and pill_widget are module-level variables
 | 
						|
    current_group_id = group_id;
 | 
						|
 | 
						|
    pill_widget = add_subscribers_pill.create({
 | 
						|
        $pill_container,
 | 
						|
        get_potential_subscribers: get_potential_members,
 | 
						|
    });
 | 
						|
 | 
						|
    make_list_widget({
 | 
						|
        $parent_container,
 | 
						|
        name: "user_group_members",
 | 
						|
        user_ids: Array.from(group.members),
 | 
						|
    });
 | 
						|
}
 | 
						|
 | 
						|
function show_user_group_membership_request_result({
 | 
						|
    message,
 | 
						|
    add_class,
 | 
						|
    remove_class,
 | 
						|
    subscribed_users,
 | 
						|
    already_subscribed_users,
 | 
						|
    ignored_deactivated_users,
 | 
						|
}) {
 | 
						|
    const $user_group_subscription_req_result_elem = $(
 | 
						|
        ".user_group_subscription_request_result",
 | 
						|
    ).expectOne();
 | 
						|
    const html = render_user_group_subscription_request_result({
 | 
						|
        message,
 | 
						|
        subscribed_users,
 | 
						|
        already_subscribed_users,
 | 
						|
        ignored_deactivated_users,
 | 
						|
    });
 | 
						|
    ui.get_content_element($user_group_subscription_req_result_elem).html(html);
 | 
						|
    if (add_class) {
 | 
						|
        $user_group_subscription_req_result_elem.addClass(add_class);
 | 
						|
    }
 | 
						|
    if (remove_class) {
 | 
						|
        $user_group_subscription_req_result_elem.removeClass(remove_class);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
function edit_user_group_membership({group, added = [], removed = [], success, error}) {
 | 
						|
    channel.post({
 | 
						|
        url: "/json/user_groups/" + group.id + "/members",
 | 
						|
        data: {
 | 
						|
            add: JSON.stringify(added),
 | 
						|
            delete: JSON.stringify(removed),
 | 
						|
        },
 | 
						|
        success,
 | 
						|
        error,
 | 
						|
    });
 | 
						|
}
 | 
						|
 | 
						|
function add_new_members({pill_user_ids}) {
 | 
						|
    const group = user_groups.get_user_group_from_id(current_group_id);
 | 
						|
    if (!group) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    const deactivated_users = new Set();
 | 
						|
    const already_added_users = new Set();
 | 
						|
 | 
						|
    const active_user_ids = pill_user_ids.filter((user_id) => {
 | 
						|
        if (!people.is_person_active(user_id)) {
 | 
						|
            deactivated_users.add(user_id);
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
        if (user_groups.is_user_in_group(group.id, user_id)) {
 | 
						|
            // we filter out already subscribed users before sending
 | 
						|
            // add member request as the endpoint is not so robust and
 | 
						|
            // fails complete request if any already subscribed member
 | 
						|
            // is present in the request.
 | 
						|
            already_added_users.add(user_id);
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
        return true;
 | 
						|
    });
 | 
						|
 | 
						|
    const user_id_set = new Set(active_user_ids);
 | 
						|
 | 
						|
    if (
 | 
						|
        user_id_set.has(page_params.user_id) &&
 | 
						|
        user_groups.is_user_in_group(group.id, page_params.user_id)
 | 
						|
    ) {
 | 
						|
        // We don't want to send a request to add ourselves if we
 | 
						|
        // are already added to this group. This case occurs
 | 
						|
        // when creating user pills from a stream or user group.
 | 
						|
        user_id_set.delete(page_params.user_id);
 | 
						|
    }
 | 
						|
 | 
						|
    let ignored_deactivated_users;
 | 
						|
    let ignored_already_added_users;
 | 
						|
    if (deactivated_users.size > 0) {
 | 
						|
        ignored_deactivated_users = Array.from(deactivated_users);
 | 
						|
        ignored_deactivated_users = ignored_deactivated_users.map((user_id) =>
 | 
						|
            people.get_by_user_id(user_id),
 | 
						|
        );
 | 
						|
    }
 | 
						|
    if (already_added_users.size > 0) {
 | 
						|
        ignored_already_added_users = Array.from(already_added_users);
 | 
						|
        ignored_already_added_users = ignored_already_added_users.map((user_id) =>
 | 
						|
            people.get_by_user_id(user_id),
 | 
						|
        );
 | 
						|
    }
 | 
						|
 | 
						|
    if (user_id_set.size === 0) {
 | 
						|
        show_user_group_membership_request_result({
 | 
						|
            message: $t({defaultMessage: "No user to subscribe."}),
 | 
						|
            add_class: "text-error",
 | 
						|
            remove_class: "text-success",
 | 
						|
            already_subscribed_users: ignored_already_added_users,
 | 
						|
            ignored_deactivated_users,
 | 
						|
        });
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    const user_ids = Array.from(user_id_set);
 | 
						|
 | 
						|
    function invite_success() {
 | 
						|
        pill_widget.clear();
 | 
						|
        show_user_group_membership_request_result({
 | 
						|
            message: $t({defaultMessage: "Added successfully."}),
 | 
						|
            add_class: "text-success",
 | 
						|
            remove_class: "text-error",
 | 
						|
            already_subscribed_users: ignored_already_added_users,
 | 
						|
            ignored_deactivated_users,
 | 
						|
        });
 | 
						|
    }
 | 
						|
 | 
						|
    function invite_failure(xhr) {
 | 
						|
        const error = JSON.parse(xhr.responseText);
 | 
						|
        show_user_group_membership_request_result({
 | 
						|
            message: error.msg,
 | 
						|
            add_class: "text-error",
 | 
						|
            remove_class: "text-success",
 | 
						|
        });
 | 
						|
    }
 | 
						|
 | 
						|
    edit_user_group_membership({
 | 
						|
        group,
 | 
						|
        added: user_ids,
 | 
						|
        success: invite_success,
 | 
						|
        error: invite_failure,
 | 
						|
    });
 | 
						|
}
 | 
						|
 | 
						|
function remove_member({group_id, target_user_id, $list_entry}) {
 | 
						|
    const group = user_groups.get_user_group_from_id(current_group_id);
 | 
						|
    if (!group) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    function removal_success() {
 | 
						|
        if (group_id !== current_group_id) {
 | 
						|
            blueslip.info("Response for subscription removal came too late.");
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        $list_entry.remove();
 | 
						|
        const message = $t({defaultMessage: "Removed successfully."});
 | 
						|
        show_user_group_membership_request_result({
 | 
						|
            message,
 | 
						|
            add_class: "text-success",
 | 
						|
            remove_class: "text-remove",
 | 
						|
        });
 | 
						|
    }
 | 
						|
 | 
						|
    function removal_failure() {
 | 
						|
        show_user_group_membership_request_result({
 | 
						|
            message: $t({defaultMessage: "Error removing user from this group."}),
 | 
						|
            add_class: "text-error",
 | 
						|
            remove_class: "text-success",
 | 
						|
        });
 | 
						|
    }
 | 
						|
 | 
						|
    function do_remove_user_from_group() {
 | 
						|
        edit_user_group_membership({
 | 
						|
            group,
 | 
						|
            removed: [target_user_id],
 | 
						|
            success: removal_success,
 | 
						|
            error: removal_failure,
 | 
						|
        });
 | 
						|
    }
 | 
						|
 | 
						|
    if (people.is_my_user_id(target_user_id) && !page_params.is_admin) {
 | 
						|
        const html_body = render_leave_user_group_modal({
 | 
						|
            message: $t({
 | 
						|
                defaultMessage: "Once you leave this group, you will not be able to rejoin.",
 | 
						|
            }),
 | 
						|
        });
 | 
						|
 | 
						|
        confirm_dialog.launch({
 | 
						|
            html_heading: $t_html({defaultMessage: "Leave {group_name}"}, {group_name: group.name}),
 | 
						|
            html_body,
 | 
						|
            on_click: do_remove_user_from_group,
 | 
						|
        });
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    do_remove_user_from_group();
 | 
						|
}
 | 
						|
 | 
						|
export function initialize() {
 | 
						|
    add_subscribers_pill.set_up_handlers({
 | 
						|
        get_pill_widget: () => pill_widget,
 | 
						|
        $parent_container: $("#manage_groups_container"),
 | 
						|
        pill_selector: ".edit_members_for_user_group .pill-container",
 | 
						|
        button_selector: ".edit_members_for_user_group .add-subscriber-button",
 | 
						|
        action: add_new_members,
 | 
						|
    });
 | 
						|
 | 
						|
    $("#manage_groups_container").on(
 | 
						|
        "submit",
 | 
						|
        ".edit_members_for_user_group .subscriber_list_remove form",
 | 
						|
        (e) => {
 | 
						|
            e.preventDefault();
 | 
						|
 | 
						|
            const $list_entry = $(e.target).closest("tr");
 | 
						|
            const target_user_id = Number.parseInt($list_entry.attr("data-subscriber-id"), 10);
 | 
						|
            const group_id = current_group_id;
 | 
						|
 | 
						|
            remove_member({group_id, target_user_id, $list_entry});
 | 
						|
        },
 | 
						|
    );
 | 
						|
}
 |