user_groups: Add UI to set and update can_mention_group setting.

This commit adds support to set can_mention_group setting
when creating user group and also update the setting for
existing user groups.
This commit is contained in:
Sahil Batra 2023-11-27 16:06:07 +05:30 committed by Tim Abbott
parent db0476622a
commit 2968eb2b04
13 changed files with 192 additions and 11 deletions

View File

@ -259,6 +259,7 @@ EXEMPT_FILES = make_set(
"web/src/url-template.d.ts", "web/src/url-template.d.ts",
"web/src/user_card_popover.js", "web/src/user_card_popover.js",
"web/src/user_deactivation_ui.ts", "web/src/user_deactivation_ui.ts",
"web/src/user_group_components.js",
"web/src/user_group_create.js", "web/src/user_group_create.js",
"web/src/user_group_create_members.js", "web/src/user_group_create_members.js",
"web/src/user_group_create_members_data.ts", "web/src/user_group_create_members_data.ts",

View File

@ -48,7 +48,7 @@ export function get_realm_time_limits_in_minutes(property) {
return val.toString(); return val.toString();
} }
export function get_property_value(property_name, for_realm_default_settings, sub) { export function get_property_value(property_name, for_realm_default_settings, sub, group) {
if (for_realm_default_settings) { if (for_realm_default_settings) {
// realm_user_default_settings are stored in a separate object. // realm_user_default_settings are stored in a separate object.
if (property_name === "twenty_four_hour_time") { if (property_name === "twenty_four_hour_time") {
@ -74,6 +74,10 @@ export function get_property_value(property_name, for_realm_default_settings, su
return sub[property_name]; return sub[property_name];
} }
if (group) {
return group[property_name];
}
if (property_name === "realm_org_join_restrictions") { if (property_name === "realm_org_join_restrictions") {
if (page_params.realm_emails_restricted_to_domains) { if (page_params.realm_emails_restricted_to_domains) {
return "only_selected_domain"; return "only_selected_domain";
@ -240,6 +244,8 @@ export let signup_notifications_stream_widget = null;
export let create_multiuse_invite_group_widget = null; export let create_multiuse_invite_group_widget = null;
export let can_remove_subscribers_group_widget = null; export let can_remove_subscribers_group_widget = null;
export let can_access_all_users_group_widget = null; export let can_access_all_users_group_widget = null;
export let can_mention_group_widget = null;
export let new_group_can_mention_group_widget = null;
export function get_widget_for_dropdown_list_settings(property_name) { export function get_widget_for_dropdown_list_settings(property_name) {
switch (property_name) { switch (property_name) {
@ -255,6 +261,8 @@ export function get_widget_for_dropdown_list_settings(property_name) {
return can_remove_subscribers_group_widget; return can_remove_subscribers_group_widget;
case "realm_can_access_all_users_group": case "realm_can_access_all_users_group":
return can_access_all_users_group_widget; return can_access_all_users_group_widget;
case "can_mention_group":
return can_mention_group_widget;
default: default:
blueslip.error("No dropdown list widget for property", {property_name}); blueslip.error("No dropdown list widget for property", {property_name});
return null; return null;
@ -285,6 +293,14 @@ export function set_can_access_all_users_group_widget(widget) {
can_access_all_users_group_widget = widget; can_access_all_users_group_widget = widget;
} }
export function set_can_mention_group_widget(widget) {
can_mention_group_widget = widget;
}
export function set_new_group_can_mention_group_widget(widget) {
new_group_can_mention_group_widget = widget;
}
export function set_dropdown_list_widget_setting_value(property_name, value) { export function set_dropdown_list_widget_setting_value(property_name, value) {
const widget = get_widget_for_dropdown_list_settings(property_name); const widget = get_widget_for_dropdown_list_settings(property_name);
widget.render(value); widget.render(value);
@ -475,10 +491,10 @@ function get_time_limit_setting_value($input_elem, for_api_data = true) {
return parse_time_limit($custom_input_elem); return parse_time_limit($custom_input_elem);
} }
export function check_property_changed(elem, for_realm_default_settings, sub) { export function check_property_changed(elem, for_realm_default_settings, sub, group) {
const $elem = $(elem); const $elem = $(elem);
const property_name = extract_property_name($elem, for_realm_default_settings); const property_name = extract_property_name($elem, for_realm_default_settings);
let current_val = get_property_value(property_name, for_realm_default_settings, sub); let current_val = get_property_value(property_name, for_realm_default_settings, sub, group);
let proposed_val; let proposed_val;
switch (property_name) { switch (property_name) {
@ -493,6 +509,7 @@ export function check_property_changed(elem, for_realm_default_settings, sub) {
case "realm_default_code_block_language": case "realm_default_code_block_language":
case "can_remove_subscribers_group": case "can_remove_subscribers_group":
case "realm_create_multiuse_invite_group": case "realm_create_multiuse_invite_group":
case "can_mention_group":
proposed_val = get_dropdown_list_widget_setting_value($elem); proposed_val = get_dropdown_list_widget_setting_value($elem);
break; break;
case "email_notifications_batching_period_seconds": case "email_notifications_batching_period_seconds":
@ -545,12 +562,17 @@ function switching_to_private(properties_elements, for_realm_default_settings) {
return false; return false;
} }
export function save_discard_widget_status_handler($subsection, for_realm_default_settings, sub) { export function save_discard_widget_status_handler(
$subsection,
for_realm_default_settings,
sub,
group,
) {
$subsection.find(".subsection-failed-status p").hide(); $subsection.find(".subsection-failed-status p").hide();
$subsection.find(".save-button").show(); $subsection.find(".save-button").show();
const properties_elements = get_subsection_property_elements($subsection); const properties_elements = get_subsection_property_elements($subsection);
const show_change_process_button = properties_elements.some((elem) => const show_change_process_button = properties_elements.some((elem) =>
check_property_changed(elem, for_realm_default_settings, sub), check_property_changed(elem, for_realm_default_settings, sub, group),
); );
const $save_btn_controls = $subsection.find(".subsection-header .save-button-controls"); const $save_btn_controls = $subsection.find(".subsection-header .save-button-controls");

View File

@ -447,7 +447,7 @@ function update_dependent_subsettings(property_name) {
} }
} }
export function discard_property_element_changes(elem, for_realm_default_settings, sub) { export function discard_property_element_changes(elem, for_realm_default_settings, sub, group) {
const $elem = $(elem); const $elem = $(elem);
const property_name = settings_components.extract_property_name( const property_name = settings_components.extract_property_name(
$elem, $elem,
@ -457,6 +457,7 @@ export function discard_property_element_changes(elem, for_realm_default_setting
property_name, property_name,
for_realm_default_settings, for_realm_default_settings,
sub, sub,
group,
); );
switch (property_name) { switch (property_name) {
@ -478,6 +479,7 @@ export function discard_property_element_changes(elem, for_realm_default_setting
case "can_remove_subscribers_group": case "can_remove_subscribers_group":
case "realm_create_multiuse_invite_group": case "realm_create_multiuse_invite_group":
case "realm_can_access_all_users_group": case "realm_can_access_all_users_group":
case "can_mention_group":
settings_components.set_dropdown_list_widget_setting_value( settings_components.set_dropdown_list_widget_setting_value(
property_name, property_name,
property_value, property_value,
@ -767,19 +769,24 @@ export function init_dropdown_widgets() {
can_access_all_users_group_widget.setup(); can_access_all_users_group_widget.setup();
} }
export function populate_data_for_request(subsection, for_realm_default_settings, sub) { export function populate_data_for_request(subsection, for_realm_default_settings, sub, group) {
let data = {}; let data = {};
const properties_elements = settings_components.get_subsection_property_elements(subsection); const properties_elements = settings_components.get_subsection_property_elements(subsection);
for (const input_elem of properties_elements) { for (const input_elem of properties_elements) {
const $input_elem = $(input_elem); const $input_elem = $(input_elem);
if ( if (
settings_components.check_property_changed($input_elem, for_realm_default_settings, sub) settings_components.check_property_changed(
$input_elem,
for_realm_default_settings,
sub,
group,
)
) { ) {
const input_value = settings_components.get_input_element_value($input_elem); const input_value = settings_components.get_input_element_value($input_elem);
if (input_value !== undefined) { if (input_value !== undefined) {
let property_name; let property_name;
if (for_realm_default_settings || sub) { if (for_realm_default_settings || sub || group) {
property_name = settings_components.extract_property_name( property_name = settings_components.extract_property_name(
$input_elem, $input_elem,
for_realm_default_settings, for_realm_default_settings,

View File

@ -159,6 +159,7 @@ export type UserGroupUpdateEvent = {
data: { data: {
name?: string; name?: string;
description?: string; description?: string;
can_mention_group?: number;
}; };
}; };

View File

@ -0,0 +1,55 @@
import $ from "jquery";
import * as dropdown_widget from "./dropdown_widget";
import * as settings_components from "./settings_components";
import * as user_groups from "./user_groups";
export function setup_permissions_dropdown(group, for_group_creation) {
let widget_name;
let default_id;
if (for_group_creation) {
widget_name = "new_group_can_mention_group";
default_id = user_groups.get_user_group_from_name("role:everyone").id;
} else {
widget_name = "can_mention_group";
default_id = group.can_mention_group;
}
const can_mention_group_widget = new dropdown_widget.DropdownWidget({
widget_name,
get_options: () =>
user_groups.get_realm_user_groups_for_dropdown_list_widget(
"can_mention_group",
"group",
),
item_click_callback(event, dropdown) {
dropdown.hide();
event.preventDefault();
event.stopPropagation();
can_mention_group_widget.render();
if (!for_group_creation) {
settings_components.save_discard_widget_status_handler(
$("#group_permission_settings"),
false,
undefined,
group,
);
}
},
$events_container: $("#groups_overlay .group-permissions"),
tippy_props: {
placement: "bottom-start",
},
default_id,
unique_id_type: dropdown_widget.DATA_TYPES.NUMBER,
on_mount_callback(dropdown) {
$(dropdown.popper).css("min-width", "300px");
},
});
if (for_group_creation) {
settings_components.set_new_group_can_mention_group_widget(can_mention_group_widget);
} else {
settings_components.set_can_mention_group_widget(can_mention_group_widget);
}
can_mention_group_widget.setup();
}

View File

@ -4,7 +4,9 @@ import * as channel from "./channel";
import {$t, $t_html} from "./i18n"; import {$t, $t_html} from "./i18n";
import * as keydown_util from "./keydown_util"; import * as keydown_util from "./keydown_util";
import * as loading from "./loading"; import * as loading from "./loading";
import * as settings_components from "./settings_components";
import * as ui_report from "./ui_report"; import * as ui_report from "./ui_report";
import * as user_group_components from "./user_group_components";
import * as user_group_create_members from "./user_group_create_members"; import * as user_group_create_members from "./user_group_create_members";
import * as user_group_create_members_data from "./user_group_create_members_data"; import * as user_group_create_members_data from "./user_group_create_members_data";
import * as user_groups from "./user_groups"; import * as user_groups from "./user_groups";
@ -122,6 +124,10 @@ function create_user_group() {
const user_ids = user_group_create_members.get_principals(); const user_ids = user_group_create_members.get_principals();
data.members = JSON.stringify(user_ids); data.members = JSON.stringify(user_ids);
data.can_mention_group = Number.parseInt(
settings_components.new_group_can_mention_group_widget.value(),
10,
);
loading.make_indicator($("#user_group_creating_indicator"), { loading.make_indicator($("#user_group_creating_indicator"), {
text: $t({defaultMessage: "Creating group..."}), text: $t({defaultMessage: "Creating group..."}),
}); });
@ -192,4 +198,6 @@ export function set_up_handlers() {
e.preventDefault(); e.preventDefault();
} }
}); });
user_group_components.setup_permissions_dropdown(undefined, true);
} }

View File

@ -20,9 +20,12 @@ import * as overlays from "./overlays";
import {page_params} from "./page_params"; import {page_params} from "./page_params";
import * as people from "./people"; import * as people from "./people";
import * as scroll_util from "./scroll_util"; import * as scroll_util from "./scroll_util";
import * as settings_components from "./settings_components";
import * as settings_data from "./settings_data"; import * as settings_data from "./settings_data";
import * as settings_org from "./settings_org";
import * as stream_ui_updates from "./stream_ui_updates"; import * as stream_ui_updates from "./stream_ui_updates";
import * as ui_report from "./ui_report"; 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_create from "./user_group_create";
import * as user_group_edit_members from "./user_group_edit_members"; import * as user_group_edit_members from "./user_group_edit_members";
import * as user_groups from "./user_groups"; import * as user_groups from "./user_groups";
@ -241,6 +244,13 @@ export function update_settings_pane(group) {
const $edit_container = get_edit_container(group); const $edit_container = get_edit_container(group);
$edit_container.find(".group-name").text(group.name); $edit_container.find(".group-name").text(group.name);
$edit_container.find(".group-description").text(group.description); $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() { function update_toggler_for_group_setting() {
@ -267,6 +277,9 @@ export function show_settings_for(group) {
$edit_container.show(); $edit_container.show();
show_membership_settings(group); show_membership_settings(group);
user_group_components.setup_permissions_dropdown(group, false);
$edit_container.find("button").prop("disabled", !settings_data.can_edit_user_group(group.id));
} }
export function setup_group_settings(group) { export function setup_group_settings(group) {
@ -879,6 +892,48 @@ export function initialize() {
const $group_row = row_for_group_id(user_group_id); const $group_row = row_for_group_id(user_group_id);
add_or_remove_from_group(user_group, $group_row); 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) { export function launch(section) {

View File

@ -78,6 +78,12 @@ export function update(event: UserGroupUpdateEvent): void {
user_group_name_dict.delete(group.name); user_group_name_dict.delete(group.name);
user_group_name_dict.set(group.name, group); user_group_name_dict.set(group.name, group);
} }
if (event.data.can_mention_group !== undefined) {
group.can_mention_group = event.data.can_mention_group;
user_group_name_dict.delete(group.name);
user_group_name_dict.set(group.name, group);
}
} }
export function get_user_group_from_name(name: string): UserGroup | undefined { export function get_user_group_from_name(name: string): UserGroup | undefined {

View File

@ -835,7 +835,8 @@ div.overlay {
} }
#stream_settings .save-button-controls, #stream_settings .save-button-controls,
#settings_page .save-button-controls { #settings_page .save-button-controls,
#user_group_settings .save-button-controls {
display: inline; display: inline;
margin-left: 15px; margin-left: 15px;

View File

@ -1008,7 +1008,8 @@ div.settings-radio-input-parent {
} }
.stream-permissions, .stream-permissions,
.stream-creation-body { .stream-creation-body,
.group-permissions {
.input-group { .input-group {
margin-bottom: 10px; margin-bottom: 10px;

View File

@ -0,0 +1,4 @@
{{> ../dropdown_widget_with_label
widget_name=can_mention_group_widget_name
label=(t 'Who can mention this group?')
value_type="number"}}

View File

@ -20,6 +20,16 @@
<input type="text" name="user_group_description" id="create_user_group_description" class="settings_text_input" <input type="text" name="user_group_description" id="create_user_group_description" class="settings_text_input"
placeholder="{{t 'User group description' }}" value="" autocomplete="off" /> placeholder="{{t 'User group description' }}" value="" autocomplete="off" />
</section> </section>
<section class="block">
<div class="group-permissions settings-subsection-parent" id="new_group_permission_settings">
<div class="subsection-header">
<h3 class="user_group_setting_subsection_title">{{t "Group permissions" }}
</h3>
</div>
{{> group_permissions can_mention_group_widget_name="new_group_can_mention_group"}}
</div>
</section>
<section class="block"> <section class="block">
<label for="people_to_add_in_group"> <label for="people_to_add_in_group">
<h4 class="user_group_setting_subsection_title">{{t "Choose members" }}</h4> <h4 class="user_group_setting_subsection_title">{{t "Choose members" }}</h4>

View File

@ -35,6 +35,16 @@
{{group.description}} {{group.description}}
</span> </span>
</div> </div>
<div class="group-permissions settings-subsection-parent" id="group_permission_settings">
<div class="subsection-header">
<h3 class="user_group_setting_subsection_title">{{t "Group permissions" }}
</h3>
{{> ../settings/settings_save_discard_widget section_name="group-permissions" }}
</div>
{{> group_permissions can_mention_group_widget_name="can_mention_group"}}
</div>
</div> </div>
<div class="group_member_settings group_setting_section"> <div class="group_member_settings group_setting_section">