mirror of https://github.com/zulip/zulip.git
982 lines
33 KiB
JavaScript
982 lines
33 KiB
JavaScript
import $ from "jquery";
|
|
|
|
import render_confirm_delete_user from "../templates/confirm_dialog/confirm_delete_user.hbs";
|
|
import render_browse_user_groups_list_item from "../templates/user_group_settings/browse_user_groups_list_item.hbs";
|
|
import render_change_user_group_info_modal from "../templates/user_group_settings/change_user_group_info_modal.hbs";
|
|
import render_user_group_settings from "../templates/user_group_settings/user_group_settings.hbs";
|
|
import render_user_group_settings_overlay from "../templates/user_group_settings/user_group_settings_overlay.hbs";
|
|
|
|
import * as blueslip from "./blueslip";
|
|
import * as browser_history from "./browser_history";
|
|
import * as channel from "./channel";
|
|
import * as components from "./components";
|
|
import * as confirm_dialog from "./confirm_dialog";
|
|
import * as dialog_widget from "./dialog_widget";
|
|
import * as hash_util from "./hash_util";
|
|
import {$t, $t_html} from "./i18n";
|
|
import * as ListWidget from "./list_widget";
|
|
import * as loading from "./loading";
|
|
import * as overlays from "./overlays";
|
|
import * as people from "./people";
|
|
import * as scroll_util from "./scroll_util";
|
|
import * as settings_components from "./settings_components";
|
|
import * as settings_data from "./settings_data";
|
|
import * as settings_org from "./settings_org";
|
|
import {current_user, realm} from "./state_data";
|
|
import * as ui_report from "./ui_report";
|
|
import * as user_group_components from "./user_group_components";
|
|
import * as user_group_create from "./user_group_create";
|
|
import * as user_group_edit_members from "./user_group_edit_members";
|
|
import * as user_groups from "./user_groups";
|
|
import * as util from "./util";
|
|
|
|
export let toggler;
|
|
export let select_tab = "general";
|
|
|
|
let group_list_widget;
|
|
let group_list_toggler;
|
|
let active_group_id;
|
|
|
|
function get_user_group_id(target) {
|
|
const $row = $(target).closest(
|
|
".group-row, .user_group_settings_wrapper, .save-button, .group_settings_header",
|
|
);
|
|
return Number.parseInt($row.attr("data-group-id"), 10);
|
|
}
|
|
|
|
function get_user_group_for_target(target) {
|
|
const user_group_id = get_user_group_id(target);
|
|
if (!user_group_id) {
|
|
blueslip.error("Cannot find user group id for target");
|
|
return undefined;
|
|
}
|
|
|
|
const group = user_groups.get_user_group_from_id(user_group_id);
|
|
if (!group) {
|
|
blueslip.error("get_user_group_for_target() failed id lookup", {user_group_id});
|
|
return undefined;
|
|
}
|
|
return group;
|
|
}
|
|
|
|
export function get_edit_container(group) {
|
|
return $(
|
|
`#groups_overlay .user_group_settings_wrapper[data-group-id='${CSS.escape(group.id)}']`,
|
|
);
|
|
}
|
|
|
|
function update_add_members_elements(group) {
|
|
if (!is_editing_group(group.id)) {
|
|
return;
|
|
}
|
|
|
|
// We are only concerned with the Members tab for editing groups.
|
|
const $add_members_container = $(".edit_members_for_user_group .add_members_container");
|
|
|
|
if (current_user.is_guest || realm.realm_is_zephyr_mirror_realm) {
|
|
// For guest users, we just hide the add_members feature.
|
|
$add_members_container.hide();
|
|
return;
|
|
}
|
|
|
|
// Otherwise, we adjust whether the widgets are disabled based on
|
|
// whether this user is authorized to add members.
|
|
const $input_element = $add_members_container.find(".input").expectOne();
|
|
const $button_element = $add_members_container.find('button[name="add_member"]').expectOne();
|
|
|
|
if (settings_data.can_edit_user_group(group.id)) {
|
|
$input_element.prop("contenteditable", true);
|
|
$button_element.prop("disabled", false);
|
|
$button_element.css("pointer-events", "");
|
|
$add_members_container[0]._tippy?.destroy();
|
|
$add_members_container.removeClass("add_members_disabled");
|
|
} else {
|
|
$input_element.prop("contenteditable", false);
|
|
$button_element.prop("disabled", true);
|
|
$add_members_container.addClass("add_members_disabled");
|
|
|
|
settings_components.initialize_disable_btn_hint_popover(
|
|
$add_members_container,
|
|
$t({defaultMessage: "Only group members can add users to a group."}),
|
|
);
|
|
}
|
|
}
|
|
|
|
function show_membership_settings(group) {
|
|
const $edit_container = get_edit_container(group);
|
|
update_add_members_elements(group);
|
|
|
|
const $member_container = $edit_container.find(".edit_members_for_user_group");
|
|
user_group_edit_members.enable_member_management({
|
|
group,
|
|
$parent_container: $member_container,
|
|
});
|
|
}
|
|
|
|
function enable_group_edit_settings(group) {
|
|
if (!is_editing_group(group.id)) {
|
|
return;
|
|
}
|
|
const $edit_container = get_edit_container(group);
|
|
$edit_container.find(".group-header .button-group").show();
|
|
$edit_container.find(".member-list .actions").show();
|
|
update_add_members_elements(group);
|
|
}
|
|
|
|
function disable_group_edit_settings(group) {
|
|
if (!is_editing_group(group.id)) {
|
|
return;
|
|
}
|
|
const $edit_container = get_edit_container(group);
|
|
$edit_container.find(".group-header .button-group").hide();
|
|
$edit_container.find(".member-list .user-remove-actions").hide();
|
|
update_add_members_elements(group);
|
|
}
|
|
|
|
function group_membership_button(group_id) {
|
|
return $(`.group_settings_header[data-group-id='${CSS.escape(group_id)}'] .join_leave_button`);
|
|
}
|
|
|
|
function initialize_tooltip_for_membership_button(group_id) {
|
|
const $tooltip_wrapper = group_membership_button(group_id).closest(
|
|
".join_leave_button_wrapper",
|
|
);
|
|
const is_member = user_groups.is_user_in_group(group_id, people.my_current_user_id());
|
|
let tooltip_message;
|
|
if (is_member) {
|
|
tooltip_message = $t({defaultMessage: "You do not have permission to leave this group."});
|
|
} else {
|
|
tooltip_message = $t({defaultMessage: "You do not have permission to join this group."});
|
|
}
|
|
settings_components.initialize_disable_btn_hint_popover($tooltip_wrapper, tooltip_message);
|
|
}
|
|
|
|
function update_group_membership_button(group_id) {
|
|
const $group_settings_button = group_membership_button(group_id);
|
|
|
|
if (!$group_settings_button.length) {
|
|
return;
|
|
}
|
|
|
|
const is_member = user_groups.is_user_in_group(group_id, people.my_current_user_id());
|
|
if (is_member) {
|
|
$group_settings_button.text($t({defaultMessage: "Leave group"}));
|
|
} else {
|
|
$group_settings_button.text($t({defaultMessage: "Join group"}));
|
|
}
|
|
|
|
if (settings_data.can_edit_user_group(group_id)) {
|
|
$group_settings_button.prop("disabled", false);
|
|
$group_settings_button.css("pointer-events", "");
|
|
} else {
|
|
$group_settings_button.prop("disabled", true);
|
|
initialize_tooltip_for_membership_button(group_id);
|
|
}
|
|
}
|
|
|
|
export function handle_member_edit_event(group_id, user_ids) {
|
|
if (!overlays.groups_open()) {
|
|
return;
|
|
}
|
|
const group = user_groups.get_user_group_from_id(group_id);
|
|
|
|
// update members list if currently rendered.
|
|
if (is_editing_group(group_id)) {
|
|
user_group_edit_members.update_member_list_widget(group);
|
|
if (user_ids.includes(people.my_current_user_id())) {
|
|
update_group_membership_button(group_id);
|
|
}
|
|
}
|
|
|
|
// update display of group-rows on left panel.
|
|
// We need this update only if your-groups tab is active
|
|
// and current user is among the affect users as in that
|
|
// case the group widget list need to be updated and show
|
|
// or remove the group-row on the left panel accordingly.
|
|
const tab_key = get_active_data().$tabs.first().attr("data-tab-key");
|
|
if (tab_key === "your-groups" && user_ids.includes(people.my_current_user_id())) {
|
|
if (user_groups.is_user_in_group(group_id, people.my_current_user_id())) {
|
|
// We add the group row to list if the current user
|
|
// is added to it. The whole list is redrawed to
|
|
// maintain the sorted order of groups.
|
|
redraw_user_group_list();
|
|
} else if (!settings_data.can_edit_user_group(group_id)) {
|
|
// We remove the group row immediately only if the
|
|
// user cannot join the group again themselves.
|
|
const group_row = row_for_group_id(group_id);
|
|
if (group_row.length) {
|
|
group_row.remove();
|
|
update_empty_left_panel_message();
|
|
}
|
|
}
|
|
}
|
|
|
|
// update display of check-mark.
|
|
if (is_group_already_present(group)) {
|
|
const $row = row_for_group_id(group_id);
|
|
|
|
const item = group;
|
|
item.is_member = user_groups.is_user_in_group(group_id, people.my_current_user_id());
|
|
item.can_edit = settings_data.can_edit_user_group(item.id);
|
|
const html = render_browse_user_groups_list_item(item);
|
|
const $new_row = $(html);
|
|
|
|
// TODO: Remove this if/when we just handle "active" when rendering templates.
|
|
if ($row.hasClass("active")) {
|
|
$new_row.addClass("active");
|
|
}
|
|
|
|
$row.replaceWith($new_row);
|
|
}
|
|
|
|
if (
|
|
!is_editing_group(group_id) &&
|
|
user_ids.includes(people.my_current_user_id()) &&
|
|
user_groups.is_user_in_group(group_id, people.my_current_user_id())
|
|
) {
|
|
const $group_row = row_for_group_id(group.id);
|
|
open_group_edit_panel_for_row($group_row);
|
|
}
|
|
|
|
// update_settings buttons.
|
|
if (settings_data.can_edit_user_group(group_id)) {
|
|
enable_group_edit_settings(group);
|
|
} else {
|
|
disable_group_edit_settings(group);
|
|
}
|
|
}
|
|
|
|
export function update_settings_pane(group) {
|
|
const $edit_container = get_edit_container(group);
|
|
$edit_container.find(".group-name").text(group.name);
|
|
$edit_container.find(".group-description").text(group.description);
|
|
|
|
settings_org.discard_property_element_changes(
|
|
$("#id_can_mention_group"),
|
|
false,
|
|
undefined,
|
|
group,
|
|
);
|
|
}
|
|
|
|
function update_toggler_for_group_setting() {
|
|
toggler.goto(select_tab);
|
|
}
|
|
|
|
export function show_settings_for(group) {
|
|
const html = render_user_group_settings({
|
|
group,
|
|
can_edit: settings_data.can_edit_user_group(group.id),
|
|
is_member: user_groups.is_direct_member_of(people.my_current_user_id(), group.id),
|
|
});
|
|
|
|
scroll_util.get_content_element($("#user_group_settings")).html(html);
|
|
update_toggler_for_group_setting();
|
|
|
|
if (!settings_data.can_edit_user_group(group.id)) {
|
|
initialize_tooltip_for_membership_button(group.id);
|
|
}
|
|
|
|
toggler.get().prependTo("#user_group_settings .tab-container");
|
|
const $edit_container = get_edit_container(group);
|
|
$(".nothing-selected").hide();
|
|
|
|
$edit_container.show();
|
|
show_membership_settings(group);
|
|
user_group_components.setup_permissions_dropdown(group, false);
|
|
}
|
|
|
|
export function setup_group_settings(group) {
|
|
toggler = components.toggle({
|
|
child_wants_focus: true,
|
|
values: [
|
|
{label: $t({defaultMessage: "General"}), key: "general"},
|
|
{label: $t({defaultMessage: "Members"}), key: "members"},
|
|
],
|
|
callback(_name, key) {
|
|
$(".group_setting_section").hide();
|
|
$(`[data-group-section="${CSS.escape(key)}"]`).show();
|
|
select_tab = key;
|
|
const hash = hash_util.group_edit_url(group, select_tab);
|
|
browser_history.update(hash);
|
|
},
|
|
});
|
|
|
|
show_settings_for(group);
|
|
}
|
|
|
|
export function setup_group_list_tab_hash(tab_key_value) {
|
|
/*
|
|
We do not update the hash based on tab switches if
|
|
a group is currently being edited.
|
|
*/
|
|
if (get_active_data().id !== undefined) {
|
|
return;
|
|
}
|
|
|
|
if (tab_key_value === "all-groups") {
|
|
browser_history.update("#groups/all");
|
|
} else if (tab_key_value === "your-groups") {
|
|
browser_history.update("#groups/your");
|
|
} else {
|
|
blueslip.debug(`Unknown tab_key_value: ${tab_key_value} for groups overlay.`);
|
|
}
|
|
}
|
|
|
|
function display_membership_toggle_spinner(group_row) {
|
|
/* Prevent sending multiple requests by removing the button class. */
|
|
$(group_row).find(".check").removeClass("join_leave_button");
|
|
|
|
/* Hide the tick. */
|
|
const $tick = $(group_row).find("svg");
|
|
$tick.addClass("hide");
|
|
|
|
/* Add a spinner to show the request is in process. */
|
|
const $spinner = $(group_row).find(".join_leave_status").expectOne();
|
|
$spinner.show();
|
|
loading.make_indicator($spinner);
|
|
}
|
|
|
|
function hide_membership_toggle_spinner(group_row) {
|
|
/* Re-enable the button to handle requests. */
|
|
$(group_row).find(".check").addClass("join_leave_button");
|
|
|
|
/* Show the tick. */
|
|
const $tick = $(group_row).find("svg");
|
|
$tick.removeClass("hide");
|
|
|
|
/* Destroy the spinner. */
|
|
const $spinner = $(group_row).find(".join_leave_status").expectOne();
|
|
loading.destroy_indicator($spinner);
|
|
}
|
|
|
|
export const show_user_group_settings_pane = {
|
|
nothing_selected() {
|
|
$("#groups_overlay .settings, #user-group-creation").hide();
|
|
reset_active_group_id();
|
|
$("#groups_overlay .nothing-selected").show();
|
|
$("#groups_overlay .user-group-info-title").text(
|
|
$t({defaultMessage: "User group settings"}),
|
|
);
|
|
},
|
|
settings(group) {
|
|
$("#groups_overlay .nothing-selected, #user-group-creation").hide();
|
|
$("#groups_overlay .settings").show();
|
|
set_active_group_id(group.id);
|
|
$("#groups_overlay .user-group-info-title").text(group.name);
|
|
},
|
|
create_user_group() {
|
|
$("#groups_overlay .nothing-selected, #groups_overlay .settings").hide();
|
|
reset_active_group_id();
|
|
$("#user-group-creation").show();
|
|
$("#groups_overlay .user-group-info-title").text($t({defaultMessage: "Create user group"}));
|
|
},
|
|
};
|
|
|
|
function empty_right_panel() {
|
|
$(".group-row.active").removeClass("active");
|
|
show_user_group_settings_pane.nothing_selected();
|
|
}
|
|
|
|
function open_right_panel_empty() {
|
|
empty_right_panel();
|
|
const tab_key = $(".user-groups-container")
|
|
.find("div.ind-tab.selected")
|
|
.first()
|
|
.attr("data-tab-key");
|
|
setup_group_list_tab_hash(tab_key);
|
|
}
|
|
|
|
export function is_editing_group(desired_group_id) {
|
|
if (!overlays.groups_open()) {
|
|
return false;
|
|
}
|
|
return get_active_data().id === desired_group_id;
|
|
}
|
|
|
|
export function handle_deleted_group(group_id) {
|
|
if (!overlays.groups_open()) {
|
|
return;
|
|
}
|
|
|
|
if (is_editing_group(group_id)) {
|
|
open_right_panel_empty();
|
|
}
|
|
redraw_user_group_list();
|
|
}
|
|
|
|
export function show_group_settings(group) {
|
|
$(".group-row.active").removeClass("active");
|
|
show_user_group_settings_pane.settings(group);
|
|
row_for_group_id(group.id).addClass("active");
|
|
setup_group_settings(group);
|
|
}
|
|
|
|
export function open_group_edit_panel_for_row(group_row) {
|
|
const group = get_user_group_for_target(group_row);
|
|
show_group_settings(group);
|
|
}
|
|
|
|
export function set_active_group_id(group_id) {
|
|
active_group_id = group_id;
|
|
}
|
|
|
|
export function reset_active_group_id() {
|
|
active_group_id = undefined;
|
|
}
|
|
|
|
// Ideally this should be included in page params.
|
|
// Like we have realm.max_stream_name_length` and
|
|
// `realm.max_stream_description_length` for streams.
|
|
export const max_user_group_name_length = 100;
|
|
|
|
export function set_up_click_handlers() {
|
|
$("#groups_overlay").on("click", ".left #clear_search_group_name", (e) => {
|
|
const $input = $("#groups_overlay .left #search_group_name");
|
|
$input.val("");
|
|
|
|
// This is a hack to rerender complete
|
|
// stream list once the text is cleared.
|
|
$input.trigger("input");
|
|
|
|
e.stopPropagation();
|
|
e.preventDefault();
|
|
});
|
|
}
|
|
|
|
function create_user_group_clicked() {
|
|
// this changes the tab switcher (settings/preview) which isn't necessary
|
|
// to a add new stream title.
|
|
show_user_group_settings_pane.create_user_group();
|
|
$(".group-row.active").removeClass("active");
|
|
|
|
user_group_create.show_new_user_group_modal();
|
|
$("#create_user_group_name").trigger("focus");
|
|
}
|
|
|
|
export function do_open_create_user_group() {
|
|
// Only call this directly for hash changes.
|
|
// Prefer open_create_user_group().
|
|
show_right_section();
|
|
create_user_group_clicked();
|
|
}
|
|
|
|
export function open_create_user_group() {
|
|
do_open_create_user_group();
|
|
browser_history.update("#groups/new");
|
|
}
|
|
|
|
export function row_for_group_id(group_id) {
|
|
return $(`.group-row[data-group-id='${CSS.escape(group_id)}']`);
|
|
}
|
|
|
|
export function is_group_already_present(group) {
|
|
return row_for_group_id(group.id).length > 0;
|
|
}
|
|
|
|
export function get_active_data() {
|
|
const $active_tabs = $(".user-groups-container").find("div.ind-tab.selected");
|
|
return {
|
|
$row: row_for_group_id(active_group_id),
|
|
id: active_group_id,
|
|
$tabs: $active_tabs,
|
|
};
|
|
}
|
|
|
|
export function switch_to_group_row(group) {
|
|
if (is_group_already_present(group)) {
|
|
/*
|
|
It is possible that this function may be called at times
|
|
when group-row for concerned group may not be present this
|
|
might occur when user manually edits the url for a group
|
|
that user is not member of and #groups overlay is open with
|
|
your-groups tab active.
|
|
|
|
To handle such cases we perform these steps only if the group
|
|
is listed in the left panel else we simply open the settings
|
|
for the concerned group.
|
|
*/
|
|
const $group_row = row_for_group_id(group.id);
|
|
const $container = $(".user-groups-list");
|
|
|
|
get_active_data().$row.removeClass("active");
|
|
$group_row.addClass("active");
|
|
|
|
scroll_util.scroll_element_into_container($group_row, $container);
|
|
}
|
|
|
|
show_group_settings(group);
|
|
}
|
|
|
|
function show_right_section() {
|
|
$(".right").addClass("show");
|
|
$(".user-groups-header").addClass("slide-left");
|
|
}
|
|
|
|
export function add_group_to_table(group) {
|
|
if (is_group_already_present(group)) {
|
|
// If a group is already listed/added in groups modal,
|
|
// then we simply return.
|
|
// This can happen in some corner cases (which might
|
|
// be backend bugs) where a realm administrator may
|
|
// get two user_group-add events.
|
|
return;
|
|
}
|
|
|
|
redraw_user_group_list();
|
|
|
|
if (user_group_create.get_name() === group.name) {
|
|
// This `user_group_create.get_name()` check tells us whether the
|
|
// group was just created in this browser window; it's a hack
|
|
// to work around the server_events code flow not having a
|
|
// good way to associate with this request because the group
|
|
// ID isn't known yet.
|
|
show_group_settings(group);
|
|
user_group_create.reset_name();
|
|
}
|
|
}
|
|
|
|
export function update_group(group_id) {
|
|
if (!overlays.groups_open()) {
|
|
return;
|
|
}
|
|
const group = user_groups.get_user_group_from_id(group_id);
|
|
const $group_row = row_for_group_id(group_id);
|
|
// update left side pane
|
|
$group_row.find(".group-name").text(group.name);
|
|
$group_row.find(".description").text(group.description);
|
|
|
|
if (get_active_data().id === group.id) {
|
|
// update right side pane
|
|
update_settings_pane(group);
|
|
// update settings title
|
|
$("#groups_overlay .user-group-info-title").text(group.name);
|
|
}
|
|
}
|
|
|
|
export function change_state(section, left_side_tab, right_side_tab) {
|
|
if (section === "new") {
|
|
do_open_create_user_group();
|
|
redraw_user_group_list();
|
|
return;
|
|
}
|
|
|
|
if (section === "all") {
|
|
group_list_toggler.goto("all-groups");
|
|
empty_right_panel();
|
|
return;
|
|
}
|
|
|
|
// if the section is a valid number.
|
|
if (/\d+/.test(section)) {
|
|
const group_id = Number.parseInt(section, 10);
|
|
const group = user_groups.get_user_group_from_id(group_id);
|
|
show_right_section();
|
|
select_tab = right_side_tab;
|
|
|
|
if (left_side_tab === undefined) {
|
|
left_side_tab = "all-groups";
|
|
if (user_groups.is_direct_member_of(current_user.user_id, group_id)) {
|
|
left_side_tab = "your-groups";
|
|
}
|
|
}
|
|
|
|
// Callback to .goto() will update browser_history unless a
|
|
// group is being edited. We are always editing a group here
|
|
// so its safe to call
|
|
if (left_side_tab !== group_list_toggler.value()) {
|
|
set_active_group_id(group.id);
|
|
group_list_toggler.goto(left_side_tab);
|
|
}
|
|
switch_to_group_row(group);
|
|
return;
|
|
}
|
|
|
|
group_list_toggler.goto("your-groups");
|
|
empty_right_panel();
|
|
}
|
|
|
|
function compare_by_name(a, b) {
|
|
return util.strcmp(a.name, b.name);
|
|
}
|
|
|
|
function redraw_left_panel(tab_name) {
|
|
let groups_list_data;
|
|
if (tab_name === "all-groups") {
|
|
groups_list_data = user_groups.get_realm_user_groups();
|
|
} else if (tab_name === "your-groups") {
|
|
groups_list_data = user_groups.get_user_groups_of_user(people.my_current_user_id());
|
|
}
|
|
groups_list_data.sort(compare_by_name);
|
|
group_list_widget.replace_list_data(groups_list_data);
|
|
update_empty_left_panel_message();
|
|
maybe_reset_right_panel(groups_list_data);
|
|
}
|
|
|
|
export function redraw_user_group_list() {
|
|
const tab_name = get_active_data().$tabs.first().attr("data-tab-key");
|
|
redraw_left_panel(tab_name);
|
|
}
|
|
|
|
export function switch_group_tab(tab_name) {
|
|
/*
|
|
This switches the groups list tab, but it doesn't update
|
|
the group_list_toggler widget. You may instead want to
|
|
use `group_list_toggler.goto`.
|
|
*/
|
|
redraw_left_panel(tab_name);
|
|
setup_group_list_tab_hash(tab_name);
|
|
}
|
|
|
|
export function add_or_remove_from_group(group, group_row) {
|
|
const user_id = people.my_current_user_id();
|
|
function success_callback() {
|
|
if (group_row.length) {
|
|
hide_membership_toggle_spinner(group_row);
|
|
}
|
|
}
|
|
|
|
function error_callback() {
|
|
if (group_row.length) {
|
|
hide_membership_toggle_spinner(group_row);
|
|
}
|
|
}
|
|
|
|
if (group_row.length) {
|
|
display_membership_toggle_spinner(group_row);
|
|
}
|
|
if (user_groups.is_direct_member_of(user_id, group.id)) {
|
|
user_group_edit_members.edit_user_group_membership({
|
|
group,
|
|
removed: [user_id],
|
|
success_callback,
|
|
error_callback,
|
|
});
|
|
} else {
|
|
user_group_edit_members.edit_user_group_membership({
|
|
group,
|
|
added: [user_id],
|
|
success_callback,
|
|
error_callback,
|
|
});
|
|
}
|
|
}
|
|
|
|
export function maybe_reset_right_panel(groups_list_data) {
|
|
if (active_group_id === undefined) {
|
|
return;
|
|
}
|
|
|
|
const group_ids = new Set(groups_list_data.map((group) => group.id));
|
|
if (!group_ids.has(active_group_id)) {
|
|
show_user_group_settings_pane.nothing_selected();
|
|
}
|
|
}
|
|
|
|
export function update_empty_left_panel_message() {
|
|
// Check if we have any groups in panel to decide whether to
|
|
// display a notice.
|
|
let has_groups;
|
|
const is_your_groups_tab_active =
|
|
get_active_data().$tabs.first().attr("data-tab-key") === "your-groups";
|
|
if (is_your_groups_tab_active) {
|
|
has_groups = user_groups.get_user_groups_of_user(people.my_current_user_id()).length;
|
|
} else {
|
|
has_groups = user_groups.get_realm_user_groups().length;
|
|
}
|
|
if (has_groups) {
|
|
$(".no-groups-to-show").hide();
|
|
return;
|
|
}
|
|
if (is_your_groups_tab_active) {
|
|
$(".all_groups_tab_empty_text").hide();
|
|
$(".your_groups_tab_empty_text").show();
|
|
} else {
|
|
$(".your_groups_tab_empty_text").hide();
|
|
$(".all_groups_tab_empty_text").show();
|
|
}
|
|
$(".no-groups-to-show").show();
|
|
}
|
|
|
|
export function setup_page(callback) {
|
|
function initialize_components() {
|
|
group_list_toggler = components.toggle({
|
|
child_wants_focus: true,
|
|
values: [
|
|
{label: $t({defaultMessage: "Your groups"}), key: "your-groups"},
|
|
{label: $t({defaultMessage: "All groups"}), key: "all-groups"},
|
|
],
|
|
callback(_label, key) {
|
|
switch_group_tab(key);
|
|
},
|
|
});
|
|
|
|
group_list_toggler.get().prependTo("#groups_overlay_container .list-toggler-container");
|
|
}
|
|
|
|
function populate_and_fill() {
|
|
const template_data = {
|
|
can_create_or_edit_user_groups: settings_data.user_can_edit_user_groups(),
|
|
max_user_group_name_length,
|
|
};
|
|
|
|
const groups_overlay_html = render_user_group_settings_overlay(template_data);
|
|
|
|
const $groups_overlay_container = scroll_util.get_content_element(
|
|
$("#groups_overlay_container"),
|
|
);
|
|
$groups_overlay_container.html(groups_overlay_html);
|
|
|
|
// Initially as the overlay is build with empty right panel,
|
|
// active_group_id is undefined.
|
|
reset_active_group_id();
|
|
|
|
const $container = $("#groups_overlay_container .user-groups-list");
|
|
|
|
/*
|
|
As change_state function called after this initial build up
|
|
redraws left panel based on active tab we avoid building extra dom
|
|
here as the required group-rows are anyway going to be created
|
|
immediately after this due to call to change_state. So we call
|
|
`ListWidget.create` with empty user groups list.
|
|
*/
|
|
group_list_widget = ListWidget.create($container, [], {
|
|
name: "user-groups-overlay",
|
|
get_item: ListWidget.default_get_item,
|
|
modifier_html(item) {
|
|
item.is_member = user_groups.is_direct_member_of(
|
|
people.my_current_user_id(),
|
|
item.id,
|
|
);
|
|
item.can_edit = settings_data.can_edit_user_group(item.id);
|
|
return render_browse_user_groups_list_item(item);
|
|
},
|
|
filter: {
|
|
$element: $("#groups_overlay_container .left #search_group_name"),
|
|
predicate(item, value) {
|
|
return (
|
|
item &&
|
|
(item.name.toLocaleLowerCase().includes(value) ||
|
|
item.description.toLocaleLowerCase().includes(value))
|
|
);
|
|
},
|
|
onupdate() {
|
|
if (active_group_id !== undefined) {
|
|
const active_group = user_groups.get_user_group_from_id(active_group_id);
|
|
if (is_group_already_present(active_group)) {
|
|
row_for_group_id(active_group_id).addClass("active");
|
|
}
|
|
}
|
|
},
|
|
},
|
|
init_sort: ["alphabetic", "name"],
|
|
$simplebar_container: $container,
|
|
});
|
|
|
|
initialize_components();
|
|
|
|
set_up_click_handlers();
|
|
user_group_create.set_up_handlers();
|
|
|
|
// show the "User group settings" header by default.
|
|
$(".display-type #user_group_settings_title").show();
|
|
|
|
if (callback) {
|
|
callback();
|
|
}
|
|
}
|
|
|
|
populate_and_fill();
|
|
}
|
|
|
|
export function initialize() {
|
|
$("#groups_overlay_container").on("click", ".group-row", function (e) {
|
|
if ($(e.target).closest(".check, .user_group_settings_wrapper").length === 0) {
|
|
open_group_edit_panel_for_row(this);
|
|
}
|
|
});
|
|
|
|
$("#groups_overlay_container").on("click", "#open_group_info_modal", (e) => {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
const user_group_id = get_user_group_id(e.target);
|
|
const user_group = user_groups.get_user_group_from_id(user_group_id);
|
|
const template_data = {
|
|
group_name: user_group.name,
|
|
group_description: user_group.description,
|
|
max_user_group_name_length,
|
|
};
|
|
const change_user_group_info_modal = render_change_user_group_info_modal(template_data);
|
|
dialog_widget.launch({
|
|
html_heading: $t_html(
|
|
{defaultMessage: "Edit {group_name}"},
|
|
{group_name: user_group.name},
|
|
),
|
|
html_body: change_user_group_info_modal,
|
|
id: "change_group_info_modal",
|
|
loading_spinner: true,
|
|
on_click: save_group_info,
|
|
post_render() {
|
|
$("#change_group_info_modal .dialog_submit_button")
|
|
.addClass("save-button")
|
|
.attr("data-group-id", user_group_id);
|
|
},
|
|
update_submit_disabled_state_on_change: true,
|
|
});
|
|
});
|
|
|
|
$("#groups_overlay_container").on("click", ".group_settings_header .btn-danger", () => {
|
|
const active_group_data = get_active_data();
|
|
const group_id = active_group_data.id;
|
|
const user_group = user_groups.get_user_group_from_id(group_id);
|
|
|
|
if (!user_group || !settings_data.can_edit_user_group(group_id)) {
|
|
return;
|
|
}
|
|
function delete_user_group() {
|
|
channel.del({
|
|
url: "/json/user_groups/" + group_id,
|
|
data: {
|
|
id: group_id,
|
|
},
|
|
success() {
|
|
active_group_data.$row.remove();
|
|
},
|
|
error(xhr) {
|
|
ui_report.error(
|
|
$t_html({defaultMessage: "Failed"}),
|
|
xhr,
|
|
$(".group_change_property_info"),
|
|
);
|
|
},
|
|
});
|
|
}
|
|
|
|
const html_body = render_confirm_delete_user({
|
|
group_name: user_group.name,
|
|
});
|
|
|
|
const user_group_name = user_group.name;
|
|
|
|
confirm_dialog.launch({
|
|
html_heading: $t_html({defaultMessage: "Delete {user_group_name}?"}, {user_group_name}),
|
|
html_body,
|
|
on_click: delete_user_group,
|
|
});
|
|
});
|
|
|
|
function save_group_info(e) {
|
|
const group = get_user_group_for_target(e.currentTarget);
|
|
|
|
const url = `/json/user_groups/${group.id}`;
|
|
const data = {};
|
|
const new_name = $("#change_user_group_name").val().trim();
|
|
const new_description = $("#change_user_group_description").val().trim();
|
|
|
|
if (new_name !== group.name) {
|
|
data.name = new_name;
|
|
}
|
|
if (new_description !== group.description) {
|
|
data.description = new_description;
|
|
}
|
|
|
|
dialog_widget.submit_api_request(channel.patch, url, data);
|
|
}
|
|
|
|
$("#groups_overlay_container").on("click", ".create_user_group_button", (e) => {
|
|
e.preventDefault();
|
|
open_create_user_group();
|
|
});
|
|
|
|
$("#groups_overlay_container").on("click", "#user_group_creation_form [data-dismiss]", (e) => {
|
|
e.preventDefault();
|
|
// we want to make sure that the click is not just a simulated
|
|
// click; this fixes an issue where hitting "Enter" would
|
|
// trigger this code path due to bootstrap magic.
|
|
if (e.clientY !== 0) {
|
|
open_right_panel_empty();
|
|
}
|
|
});
|
|
|
|
$("#groups_overlay_container").on("click", ".group-row", show_right_section);
|
|
|
|
$("#groups_overlay_container").on("click", ".fa-chevron-left", () => {
|
|
$(".right").removeClass("show");
|
|
$(".user-groups-header").removeClass("slide-left");
|
|
});
|
|
|
|
$("#groups_overlay_container").on("click", ".join_leave_button", (e) => {
|
|
if ($(e.currentTarget).hasClass("disabled")) {
|
|
// We return early if user is not allowed to join or leave a group.
|
|
return;
|
|
}
|
|
|
|
const user_group_id = get_user_group_id(e.target);
|
|
const user_group = user_groups.get_user_group_from_id(user_group_id);
|
|
const $group_row = row_for_group_id(user_group_id);
|
|
add_or_remove_from_group(user_group, $group_row);
|
|
});
|
|
|
|
$("#groups_overlay_container").on(
|
|
"click",
|
|
".subsection-header .subsection-changes-save button",
|
|
(e) => {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
const $save_button = $(e.currentTarget);
|
|
const $subsection_elem = $save_button.closest(".settings-subsection-parent");
|
|
|
|
const group_id = $save_button.closest(".user_group_settings_wrapper").data("group-id");
|
|
const group = user_groups.get_user_group_from_id(group_id);
|
|
const data = settings_org.populate_data_for_request(
|
|
$subsection_elem,
|
|
false,
|
|
undefined,
|
|
group,
|
|
);
|
|
|
|
const url = "/json/user_groups/" + group_id;
|
|
settings_org.save_organization_settings(data, $save_button, url);
|
|
},
|
|
);
|
|
|
|
$("#groups_overlay_container").on(
|
|
"click",
|
|
".subsection-header .subsection-changes-discard button",
|
|
(e) => {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
|
|
const group_id = $(e.target).closest(".user_group_settings_wrapper").data("group-id");
|
|
const group = user_groups.get_user_group_from_id(group_id);
|
|
|
|
const $subsection = $(e.target).closest(".settings-subsection-parent");
|
|
for (const elem of settings_components.get_subsection_property_elements($subsection)) {
|
|
settings_org.discard_property_element_changes(elem, false, undefined, group);
|
|
}
|
|
const $save_btn_controls = $(e.target).closest(".save-button-controls");
|
|
settings_components.change_save_button_state($save_btn_controls, "discarded");
|
|
},
|
|
);
|
|
}
|
|
|
|
export function launch(section, left_side_tab, right_side_tab) {
|
|
setup_page(() => {
|
|
overlays.open_overlay({
|
|
name: "group_subscriptions",
|
|
$overlay: $("#groups_overlay"),
|
|
on_close() {
|
|
browser_history.exit_overlay();
|
|
},
|
|
});
|
|
change_state(section, left_side_tab, right_side_tab);
|
|
});
|
|
if (!get_active_data().id) {
|
|
if (section === "new") {
|
|
$("#create_user_group_name").trigger("focus");
|
|
} else {
|
|
$("#search_group_name").trigger("focus");
|
|
}
|
|
}
|
|
}
|