diff --git a/static/js/settings_display.js b/static/js/settings_display.js index 51fc7a85b2..2281bdfd8e 100644 --- a/static/js/settings_display.js +++ b/static/js/settings_display.js @@ -68,10 +68,18 @@ export function set_up(settings_panel) { .find(`.setting_emojiset_choice[value="${CSS.escape(settings_object.emojiset)}"]`) .prop("checked", true); + if (for_realm_settings) { + // For the realm-level defaults page, we use the common + // settings_org.js handlers, so we can return early here. + return; + } + $(`${CSS.escape(language_modal_elem)} [data-dismiss]`).on("click", () => { overlays.close_modal(language_modal_elem); }); + // Common handler for sending requests to the server when an input + // element is changed. const all_display_settings = settings_config.get_all_display_settings(); for (const setting of all_display_settings.settings.user_display_settings) { container.find(`.${CSS.escape(setting)}`).on("change", function () { diff --git a/static/js/settings_notifications.js b/static/js/settings_notifications.js index 30a4d632d3..1736a77116 100644 --- a/static/js/settings_notifications.js +++ b/static/js/settings_notifications.js @@ -133,6 +133,14 @@ export function set_up(settings_panel) { set_enable_digest_emails_visibility(settings_panel); + if (for_realm_settings) { + // For the realm-level defaults page, we use the common + // settings_org.js handlers, so we can return early here. + return; + } + + // Common handler for sending requests to the server when an input + // element is changed. container.find(".notification-settings-form").on("change", "input, select", function (e) { e.preventDefault(); e.stopPropagation(); @@ -150,6 +158,10 @@ export function set_up(settings_panel) { ); }); + // This final patch of settings are ones for which we + // intentionally don't let organization administrators set + // organization-level defaults. + if (!for_realm_settings) { container.find(".send_test_notification").on("click", () => { notifications.send_test_notification( diff --git a/static/js/settings_org.js b/static/js/settings_org.js index 3ae1976851..2de8f1faec 100644 --- a/static/js/settings_org.js +++ b/static/js/settings_org.js @@ -16,6 +16,7 @@ import * as overlays from "./overlays"; import {page_params} from "./page_params"; import * as realm_icon from "./realm_icon"; import * as realm_logo from "./realm_logo"; +import {realm_user_settings_defaults} from "./realm_user_settings_defaults"; import * as settings_config from "./settings_config"; import * as settings_notifications from "./settings_notifications"; import * as settings_realm_user_settings_defaults from "./settings_realm_user_settings_defaults"; @@ -119,7 +120,15 @@ export function get_realm_time_limits_in_minutes(property) { return val.toString(); } -function get_property_value(property_name) { +function get_property_value(property_name, for_realm_default_settings) { + if (for_realm_default_settings) { + // realm_user_default_settings are stored in a separate object. + if (property_name === "twenty_four_hour_time") { + return JSON.stringify(realm_user_settings_defaults.twenty_four_hour_time); + } + return realm_user_settings_defaults[property_name]; + } + if (property_name === "realm_message_content_edit_limit_minutes") { return get_realm_time_limits_in_minutes("realm_message_content_edit_limit_seconds"); } @@ -182,12 +191,27 @@ function get_property_value(property_name) { return page_params[property_name]; } -export function extract_property_name(elem) { +export function extract_property_name(elem, for_realm_default_settings) { + if (for_realm_default_settings) { + // We use the name attribute, rather than the ID attribute, + // for realm_user_default_settings. This is because the + // display/notification settings elements do not always have + // IDs, and also the emojiset input is not compatible with the + // ID approach. + return elem.attr("name"); + } return elem.attr("id").split("-").join("_").replace("id_", ""); } function get_subsection_property_elements(element) { const subsection = $(element).closest(".org-subsection-parent"); + if (subsection.hasClass("emoji-settings")) { + // Because the emojiset widget has a unique radio button + // structure, it needs custom code. + const emojiset_elem = subsection.find("input[name='emojiset']:checked"); + const translate_emoticons_elem = subsection.find(".translate_emoticons"); + return [emojiset_elem, translate_emoticons_elem]; + } return Array.from(subsection.find(".prop-element")); } @@ -428,10 +452,10 @@ export let default_code_language_widget = null; export let notifications_stream_widget = null; export let signup_notifications_stream_widget = null; -function discard_property_element_changes(elem) { +function discard_property_element_changes(elem, for_realm_default_settings) { elem = $(elem); - const property_name = extract_property_name(elem); - const property_value = get_property_value(property_name); + const property_name = extract_property_name(elem, for_realm_default_settings); + const property_value = get_property_value(property_name, for_realm_default_settings); switch (property_name) { case "realm_authentication_methods": @@ -446,6 +470,13 @@ function discard_property_element_changes(elem) { case "realm_default_code_block_language": default_code_language_widget.render(property_value); break; + case "emojiset": + // Because the emojiset widget has a unique radio button + // structure, it needs custom reset code. + elem.closest(".org-subsection-parent") + .find(`.setting_emojiset_choice[value='${CSS.escape(property_value)}'`) + .prop("checked", true); + break; default: if (property_value !== undefined) { set_input_element_value(elem, property_value); @@ -597,6 +628,11 @@ export function get_input_element_value(input_elem, input_type) { return input_elem.val().trim(); case "number": return Number.parseInt(input_elem.val().trim(), 10); + case "radio-group": + if (input_elem.prop("checked")) { + return input_elem.val().trim(); + } + return undefined; default: return undefined; } @@ -633,10 +669,10 @@ function get_auth_method_table_data() { return new_auth_methods; } -function check_property_changed(elem) { +function check_property_changed(elem, for_realm_default_settings) { elem = $(elem); - const property_name = extract_property_name(elem); - let current_val = get_property_value(property_name); + const property_name = extract_property_name(elem, for_realm_default_settings); + let current_val = get_property_value(property_name, for_realm_default_settings); let changed_val; switch (property_name) { @@ -665,12 +701,12 @@ function check_property_changed(elem) { return current_val !== changed_val; } -export function save_discard_widget_status_handler(subsection) { +export function save_discard_widget_status_handler(subsection, for_realm_default_settings) { subsection.find(".subsection-failed-status p").hide(); subsection.find(".save-button").show(); const properties_elements = get_subsection_property_elements(subsection); const show_change_process_button = properties_elements.some((elem) => - check_property_changed(elem), + check_property_changed(elem, for_realm_default_settings), ); const save_btn_controls = subsection.find(".subsection-header .save-button-controls"); @@ -716,7 +752,11 @@ export function init_dropdown_widgets() { }); } -export function register_save_discard_widget_handlers(container, patch_url) { +export function register_save_discard_widget_handlers( + container, + patch_url, + for_realm_default_settings, +) { container.on("change input", "input, select, textarea", (e) => { e.preventDefault(); e.stopPropagation(); @@ -736,7 +776,7 @@ export function register_save_discard_widget_handlers(container, patch_url) { } const subsection = $(e.target).closest(".org-subsection-parent"); - save_discard_widget_status_handler(subsection); + save_discard_widget_status_handler(subsection, for_realm_default_settings); return undefined; }); @@ -744,7 +784,7 @@ export function register_save_discard_widget_handlers(container, patch_url) { e.preventDefault(); e.stopPropagation(); for (const elem of get_subsection_property_elements(e.target)) { - discard_property_element_changes(elem); + discard_property_element_changes(elem, for_realm_default_settings); } const save_btn_controls = $(e.target).closest(".save-button-controls"); change_save_button_state(save_btn_controls, "discarded"); @@ -875,10 +915,20 @@ export function register_save_discard_widget_handlers(container, patch_url) { for (let input_elem of properties_elements) { input_elem = $(input_elem); - if (check_property_changed(input_elem)) { + if (check_property_changed(input_elem, for_realm_default_settings)) { const input_value = get_input_element_value(input_elem); if (input_value !== undefined) { - const property_name = input_elem.attr("id").replace("id_realm_", ""); + let property_name; + if (for_realm_default_settings) { + // We use the name attribute, rather than the ID attribute, + // for realm_user_default_settings. This is because the + // display/notification settings elements do not always have + // IDs, and also the emojiset input is not compatible with the + // ID approach. + property_name = input_elem.attr("name"); + } else { + property_name = input_elem.attr("id").replace("id_realm_", ""); + } data[property_name] = input_value; } } @@ -891,13 +941,21 @@ export function register_save_discard_widget_handlers(container, patch_url) { e.preventDefault(); e.stopPropagation(); const save_button = $(e.currentTarget); - const subsection_id = save_button.attr("id").replace("org-submit-", ""); - const subsection = subsection_id.split("-").join("_"); const subsection_elem = save_button.closest(".org-subsection-parent"); + let extra_data = {}; + + if (!for_realm_default_settings) { + // The organization settings system has some coupled + // fields that must be submitted together, which is + // managed by the get_complete_data_for_subsection function. + const subsection_id = save_button.attr("id").replace("org-submit-", ""); + const subsection = subsection_id.split("-").join("_"); + extra_data = get_complete_data_for_subsection(subsection); + } const data = { ...populate_data_for_request(subsection_elem), - ...get_complete_data_for_subsection(subsection), + ...extra_data, }; save_organization_settings(data, save_button, patch_url); }); @@ -931,7 +989,7 @@ export function build_page() { set_message_content_in_email_notifications_visiblity(); set_digest_emails_weekday_visibility(); - register_save_discard_widget_handlers($(".admin-realm-form"), "/json/realm"); + register_save_discard_widget_handlers($(".admin-realm-form"), "/json/realm", false); $(".org-subsection-parent").on("keydown", "input", (e) => { e.stopPropagation(); diff --git a/static/js/settings_realm_user_settings_defaults.js b/static/js/settings_realm_user_settings_defaults.js index 92d487dce2..c125c7a54f 100644 --- a/static/js/settings_realm_user_settings_defaults.js +++ b/static/js/settings_realm_user_settings_defaults.js @@ -1,11 +1,10 @@ import $ from "jquery"; -import * as channel from "./channel"; import {page_params} from "./page_params"; import {realm_user_settings_defaults} from "./realm_user_settings_defaults"; import * as settings_display from "./settings_display"; import * as settings_notifications from "./settings_notifications"; -import * as settings_ui from "./settings_ui"; +import * as settings_org from "./settings_org"; export const realm_default_settings_panel = {}; @@ -25,31 +24,11 @@ export function set_up() { settings_display.set_up(realm_default_settings_panel); settings_notifications.set_up(realm_default_settings_panel); - container.find(".presence_enabled").on("change", (e) => { - e.preventDefault(); - e.stopPropagation(); - - const data = {presence_enabled: container.find(".presence_enabled").prop("checked")}; - settings_ui.do_settings_change( - channel.patch, - "/json/realm/user_settings_defaults", - data, - container.find(".privacy-setting-status").expectOne(), - ); - }); - - container.find(".enter_sends").on("change", (e) => { - e.preventDefault(); - e.stopPropagation(); - - const data = {enter_sends: container.find(".enter_sends").prop("checked")}; - settings_ui.do_settings_change( - channel.patch, - "/json/realm/user_settings_defaults", - data, - container.find(".other-setting-status").expectOne(), - ); - }); + settings_org.register_save_discard_widget_handlers( + container, + "/json/realm/user_settings_defaults", + true, + ); maybe_disable_widgets(); } diff --git a/static/templates/settings/display_settings.hbs b/static/templates/settings/display_settings.hbs index cd0982c30c..2c6dda3e2f 100644 --- a/static/templates/settings/display_settings.hbs +++ b/static/templates/settings/display_settings.hbs @@ -20,17 +20,17 @@ {{/unless}} -
+

{{t "Display settings" }}

- {{> settings_save_discard_widget section_name="display-settings" show_only_indicator=true }} + {{> settings_save_discard_widget section_name="display-settings" show_only_indicator=(not for_realm_settings) }}
- {{> dropdown_options_widget option_values=default_view_values}}
@@ -38,7 +38,7 @@
- {{> dropdown_options_widget option_values=color_scheme_values}}
@@ -56,21 +56,21 @@ - {{> dropdown_options_widget option_values=demote_inactive_streams_values}}
-
+

{{t "Time settings" }}

- {{> settings_save_discard_widget section_name="time-settings" show_only_indicator=true }} + {{> settings_save_discard_widget section_name="time-settings" show_only_indicator=(not for_realm_settings) }}
- {{#each twenty_four_hour_time_values}} {{/each}} @@ -78,17 +78,17 @@
-
+

{{t "Emoji settings" }}

- {{> settings_save_discard_widget section_name="emoji-settings" show_only_indicator=true }} + {{> settings_save_discard_widget section_name="emoji-settings" show_only_indicator=(not for_realm_settings) }}
{{#each settings_object.emojiset_choices}}