2021-03-11 05:43:45 +01:00
import $ from "jquery" ;
2021-02-28 01:20:46 +01:00
import pygments _data from "../generated/pygments_data.json" ;
2023-08-09 22:30:51 +02:00
import render _compose _banner from "../templates/compose_banner/compose_banner.hbs" ;
2021-06-21 10:52:02 +02:00
import render _settings _deactivate _realm _modal from "../templates/confirm_dialog/confirm_deactivate_realm.hbs" ;
2021-02-28 01:20:46 +01:00
import render _settings _admin _auth _methods _list from "../templates/settings/admin_auth_methods_list.hbs" ;
2021-03-16 23:38:59 +01:00
import * as blueslip from "./blueslip" ;
2021-02-28 01:20:46 +01:00
import * as channel from "./channel" ;
2023-08-09 22:30:51 +02:00
import * as compose _banner from "./compose_banner" ;
2021-03-25 23:20:18 +01:00
import { csrf _token } from "./csrf" ;
2022-10-11 14:20:27 +02:00
import * as dialog _widget from "./dialog_widget" ;
2023-07-19 16:14:00 +02:00
import * as dropdown _widget from "./dropdown_widget" ;
2022-05-03 08:06:40 +02:00
import { $t , $t _html , get _language _name } from "./i18n" ;
2022-09-28 08:27:24 +02:00
import * as keydown _util from "./keydown_util" ;
2021-02-28 01:20:46 +01:00
import * as loading from "./loading" ;
2023-09-07 07:53:50 +02:00
import * as notifications from "./notifications" ;
2021-03-25 22:35:45 +01:00
import { page _params } from "./page_params" ;
2021-02-28 01:20:46 +01:00
import * as realm _icon from "./realm_icon" ;
import * as realm _logo from "./realm_logo" ;
2021-09-28 09:09:52 +02:00
import { realm _user _settings _defaults } from "./realm_user_settings_defaults" ;
2021-02-28 01:20:46 +01:00
import * as settings _config from "./settings_config" ;
2023-01-20 18:29:34 +01:00
import * as settings _data from "./settings_data" ;
2021-02-28 01:20:46 +01:00
import * as settings _notifications from "./settings_notifications" ;
2021-07-20 14:51:48 +02:00
import * as settings _realm _domains from "./settings_realm_domains" ;
2021-09-30 12:00:57 +02:00
import * as settings _realm _user _settings _defaults from "./settings_realm_user_settings_defaults" ;
2021-02-28 01:20:46 +01:00
import * as settings _ui from "./settings_ui" ;
2022-10-18 11:36:52 +02:00
import * as stream _data from "./stream_data" ;
2021-04-04 15:15:18 +02:00
import * as stream _settings _data from "./stream_settings_data" ;
2021-02-28 01:20:46 +01:00
import * as ui _report from "./ui_report" ;
2023-08-03 16:06:40 +02:00
import * as user _groups from "./user_groups" ;
2023-09-28 08:53:49 +02:00
import * as util from "./util" ;
2021-02-28 01:20:46 +01:00
2019-11-02 00:06:25 +01:00
const meta = {
2017-04-08 18:13:39 +02:00
loaded : false ,
} ;
2021-02-28 01:20:46 +01:00
export function reset ( ) {
2017-04-17 16:51:27 +02:00
meta . loaded = false ;
2021-02-28 01:20:46 +01:00
}
2017-04-17 16:51:27 +02:00
2023-01-20 13:25:32 +01:00
const MAX _CUSTOM _TIME _LIMIT _SETTING _VALUE = 2147483647 ;
2023-07-19 16:14:00 +02:00
const DISABLED _STATE _ID = - 1 ;
2023-01-20 13:25:32 +01:00
2021-02-28 01:20:46 +01:00
export function maybe _disable _widgets ( ) {
2020-06-11 13:26:27 +02:00
if ( page _params . is _owner ) {
return ;
}
2020-06-11 16:24:15 +02:00
$ ( ".organization-box [data-name='auth-methods']" )
2020-07-15 00:34:28 +02:00
. find ( "input, button, select, checked" )
2020-07-22 02:59:06 +02:00
. prop ( "disabled" , true ) ;
2020-06-11 16:24:15 +02:00
2018-12-08 17:37:57 +01:00
if ( page _params . is _admin ) {
2022-10-11 14:20:27 +02:00
$ ( ".deactivate_realm_button" ) . prop ( "disabled" , true ) ;
2023-01-25 18:50:46 +01:00
$ ( "#deactivate_realm_button_container" ) . addClass ( "disabled_setting_tooltip" ) ;
2020-07-22 02:59:06 +02:00
$ ( "#org-message-retention" ) . find ( "input, select" ) . prop ( "disabled" , true ) ;
2023-08-03 16:06:40 +02:00
$ ( "#org-join-settings" ) . find ( "input, select, button" ) . prop ( "disabled" , true ) ;
2021-07-29 13:53:27 +02:00
$ ( "#id_realm_invite_required_label" ) . parent ( ) . addClass ( "control-label-disabled" ) ;
2018-12-08 17:37:57 +01:00
return ;
}
$ ( ".organization-box [data-name='organization-profile']" )
2020-07-15 00:34:28 +02:00
. find ( "input, textarea, button, select" )
2020-07-22 02:59:06 +02:00
. prop ( "disabled" , true ) ;
2018-12-08 17:37:57 +01:00
2023-01-05 16:59:18 +01:00
$ ( ".organization-box [data-name='organization-profile']" ) . find ( ".image_upload_button" ) . hide ( ) ;
2018-12-08 17:37:57 +01:00
$ ( ".organization-box [data-name='organization-settings']" )
2020-07-15 00:34:28 +02:00
. find ( "input, textarea, button, select" )
2020-07-22 02:59:06 +02:00
. prop ( "disabled" , true ) ;
2018-12-08 17:37:57 +01:00
2021-11-16 10:40:36 +01:00
$ ( ".organization-box [data-name='organization-settings']" )
. find ( ".dropdown_list_reset_button" )
. hide ( ) ;
2018-12-08 17:37:57 +01:00
$ ( ".organization-box [data-name='organization-settings']" )
2020-07-15 00:34:28 +02:00
. find ( ".control-label-disabled" )
. addClass ( "enabled" ) ;
2018-12-08 17:37:57 +01:00
$ ( ".organization-box [data-name='organization-permissions']" )
2020-07-15 00:34:28 +02:00
. find ( "input, textarea, button, select" )
2020-07-22 02:59:06 +02:00
. prop ( "disabled" , true ) ;
2018-12-08 17:37:57 +01:00
$ ( ".organization-box [data-name='organization-permissions']" )
2020-07-15 00:34:28 +02:00
. find ( ".control-label-disabled" )
. addClass ( "enabled" ) ;
2021-02-28 01:20:46 +01:00
}
2018-12-08 17:37:57 +01:00
2021-02-28 01:20:46 +01:00
export function get _sorted _options _list ( option _values _object ) {
2020-07-02 01:39:34 +02:00
const options _list = Object . keys ( option _values _object ) . map ( ( key ) => ( {
2020-02-09 04:15:38 +01:00
... option _values _object [ key ] ,
2020-07-20 22:18:43 +02:00
key ,
2020-02-09 04:15:38 +01:00
} ) ) ;
2020-01-23 07:01:34 +01:00
let comparator = ( x , y ) => x . order - y . order ;
if ( ! options _list [ 0 ] . order ) {
comparator = ( x , y ) => {
const key _x = x . key . toUpperCase ( ) ;
const key _y = y . key . toUpperCase ( ) ;
if ( key _x < key _y ) {
return - 1 ;
}
if ( key _x > key _y ) {
return 1 ;
}
return 0 ;
} ;
}
options _list . sort ( comparator ) ;
return options _list ;
2021-02-28 01:20:46 +01:00
}
2020-01-23 07:01:34 +01:00
2021-02-28 01:20:46 +01:00
export function get _organization _settings _options ( ) {
2020-01-23 07:01:34 +01:00
const options = { } ;
2021-04-28 20:39:24 +02:00
options . common _policy _values = get _sorted _options _list ( settings _config . common _policy _values ) ;
2021-02-28 01:20:46 +01:00
options . private _message _policy _values = get _sorted _options _list (
2020-07-15 00:34:28 +02:00
settings _config . private _message _policy _values ,
) ;
2021-02-28 01:20:46 +01:00
options . wildcard _mention _policy _values = get _sorted _options _list (
2020-09-14 19:26:42 +02:00
settings _config . wildcard _mention _policy _values ,
) ;
2021-05-26 12:21:37 +02:00
options . common _message _policy _values = get _sorted _options _list (
settings _config . common _message _policy _values ,
) ;
2021-07-18 18:18:28 +02:00
options . invite _to _realm _policy _values = get _sorted _options _list (
2023-06-26 23:38:08 +02:00
settings _config . email _invite _to _realm _policy _values ,
2021-07-18 18:18:28 +02:00
) ;
2022-09-28 16:30:10 +02:00
options . edit _topic _policy _values = get _sorted _options _list (
settings _config . edit _topic _policy _values ,
) ;
2022-09-29 09:03:12 +02:00
options . move _messages _between _streams _policy _values = get _sorted _options _list (
settings _config . move _messages _between _streams _policy _values ,
) ;
2020-01-23 07:01:34 +01:00
return options ;
2021-02-28 01:20:46 +01:00
}
2020-01-23 07:01:34 +01:00
2022-04-12 17:41:07 +02:00
export function get _org _type _dropdown _options ( ) {
const current _org _type = page _params . realm _org _type ;
if ( current _org _type !== 0 ) {
return settings _config . defined _org _type _values ;
}
return settings _config . all _org _type _values ;
}
2021-02-28 01:20:46 +01:00
export function get _realm _time _limits _in _minutes ( property ) {
2022-06-03 19:20:32 +02:00
if ( page _params [ property ] === null ) {
// This represents "Anytime" case.
return null ;
}
2019-11-02 00:06:25 +01:00
let val = ( page _params [ property ] / 60 ) . toFixed ( 1 ) ;
2020-10-07 09:17:30 +02:00
if ( Number . parseFloat ( val , 10 ) === Number . parseInt ( val , 10 ) ) {
val = Number . parseInt ( val , 10 ) ;
2018-04-28 15:35:14 +02:00
}
return val . toString ( ) ;
2021-02-28 01:20:46 +01:00
}
2018-04-28 15:35:14 +02:00
2022-10-18 11:03:09 +02:00
function get _property _value ( property _name , for _realm _default _settings , sub ) {
2021-09-28 09:09:52 +02:00
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 ) ;
}
2021-12-02 15:56:34 +01:00
if (
property _name === "email_notifications_batching_period_seconds" ||
property _name === "email_notification_batching_period_edit_minutes"
) {
return realm _user _settings _defaults . email _notifications _batching _period _seconds ;
}
2021-09-28 09:09:52 +02:00
return realm _user _settings _defaults [ property _name ] ;
}
2022-10-18 11:03:09 +02:00
if ( sub ) {
2022-10-18 11:36:52 +02:00
if ( property _name === "stream_privacy" ) {
return stream _data . get _stream _privacy _policy ( sub . stream _id ) ;
}
2023-07-22 12:24:55 +02:00
if ( property _name === "is_default_stream" ) {
return stream _data . is _default _stream _id ( sub . stream _id ) ;
}
2022-10-18 11:36:52 +02:00
2022-10-18 11:03:09 +02:00
return sub [ property _name ] ;
}
2020-07-15 01:29:15 +02:00
if ( property _name === "realm_org_join_restrictions" ) {
2018-07-27 23:26:29 +02:00
if ( page _params . realm _emails _restricted _to _domains ) {
2018-04-05 00:54:31 +02:00
return "only_selected_domain" ;
}
if ( page _params . realm _disallow _disposable _email _addresses ) {
return "no_disposable_email" ;
}
return "no_restriction" ;
2018-06-16 13:27:56 +02:00
}
2018-04-19 21:45:47 +02:00
return page _params [ property _name ] ;
2018-03-29 12:52:57 +02:00
}
2022-01-25 11:36:19 +01:00
export function extract _property _name ( $elem , for _realm _default _settings ) {
2021-09-28 09:09:52 +02:00
if ( for _realm _default _settings ) {
2022-09-30 16:24:36 +02:00
// ID for realm_user_default_settings elements are of the form
// "realm_{settings_name}}" because both user and realm default
// settings use the same template and each element should have
// unique id.
2023-05-11 21:49:10 +02:00
return /^realm_(.*)$/ . exec ( $elem . attr ( "id" ) . replaceAll ( "-" , "_" ) ) [ 1 ] ;
2021-09-28 09:09:52 +02:00
}
2022-07-07 10:12:16 +02:00
if ( $elem . attr ( "id" ) . startsWith ( "id_authmethod" ) ) {
// Authentication Method component IDs include authentication method name
// for uniqueness, anchored to "id_authmethod" prefix, e.g. "id_authmethodapple_<property_name>".
// We need to strip that whole construct down to extract the actual property name.
// The [\da-z]+ part of the regexp covers the auth method name itself.
// We assume it's not an empty string and can contain only digits and lowercase ASCII letters,
// this is ensured by a respective allowlist-based filter in populate_auth_methods().
return /^id_authmethod[\da-z]+_(.*)$/ . exec ( $elem . attr ( "id" ) ) [ 1 ] ;
}
2023-05-11 21:49:10 +02:00
return /^id_(.*)$/ . exec ( $elem . attr ( "id" ) . replaceAll ( "-" , "_" ) ) [ 1 ] ;
2021-02-28 01:20:46 +01:00
}
2018-03-29 12:52:57 +02:00
2022-10-18 11:56:03 +02:00
export function get _subsection _property _elements ( subsection ) {
2023-03-02 01:58:25 +01:00
return [ ... $ ( subsection ) . find ( ".prop-element" ) ] ;
2019-05-05 22:37:09 +02:00
}
2020-07-15 00:34:28 +02:00
const simple _dropdown _properties = [
2021-03-27 05:48:37 +01:00
"realm_create_private_stream_policy" ,
"realm_create_public_stream_policy" ,
2021-11-19 10:29:39 +01:00
"realm_create_web_public_stream_policy" ,
2020-07-15 00:34:28 +02:00
"realm_invite_to_stream_policy" ,
"realm_user_group_edit_policy" ,
"realm_private_message_policy" ,
2021-05-04 19:02:24 +02:00
"realm_add_custom_emoji_policy" ,
2021-05-23 21:40:20 +02:00
"realm_invite_to_realm_policy" ,
2020-09-14 19:26:42 +02:00
"realm_wildcard_mention_policy" ,
2021-04-30 09:35:20 +02:00
"realm_move_messages_between_streams_policy" ,
2021-05-26 12:21:37 +02:00
"realm_edit_topic_policy" ,
2022-04-12 17:41:07 +02:00
"realm_org_type" ,
2020-07-15 00:34:28 +02:00
] ;
2020-02-03 12:40:36 +01:00
function set _property _dropdown _value ( property _name ) {
2021-02-03 23:23:32 +01:00
$ ( ` #id_ ${ CSS . escape ( property _name ) } ` ) . val ( get _property _value ( property _name ) ) ;
2020-02-03 12:40:36 +01:00
}
2021-12-02 14:36:09 +01:00
export function change _element _block _display _property ( elem _id , show _element ) {
2022-01-25 11:36:19 +01:00
const $elem = $ ( ` # ${ CSS . escape ( elem _id ) } ` ) ;
2020-02-03 13:03:53 +01:00
if ( show _element ) {
2022-01-25 11:36:19 +01:00
$elem . parent ( ) . show ( ) ;
2020-02-03 13:03:53 +01:00
} else {
2022-01-25 11:36:19 +01:00
$elem . parent ( ) . hide ( ) ;
2020-02-03 13:03:53 +01:00
}
}
2022-12-12 18:21:08 +01:00
function set _realm _waiting _period _setting ( ) {
const setting _value = page _params . realm _waiting _period _threshold ;
const valid _limit _values = settings _config . waiting _period _threshold _dropdown _values . map (
( x ) => x . code ,
) ;
if ( valid _limit _values . includes ( setting _value ) ) {
$ ( "#id_realm_waiting_period_threshold" ) . val ( setting _value ) ;
} else {
$ ( "#id_realm_waiting_period_threshold" ) . val ( "custom_period" ) ;
}
$ ( "#id_realm_waiting_period_threshold_custom_input" ) . val ( setting _value ) ;
2020-07-15 00:34:28 +02:00
change _element _block _display _property (
2022-12-13 12:32:01 +01:00
"id_realm_waiting_period_threshold_custom_input" ,
2022-12-12 18:21:08 +01:00
$ ( "#id_realm_waiting_period_threshold" ) . val ( ) === "custom_period" ,
2020-07-15 00:34:28 +02:00
) ;
2018-04-01 08:49:10 +02:00
}
2018-01-05 15:34:10 +01:00
2023-09-19 18:10:23 +02:00
function is _video _chat _provider _jitsi _meet ( ) {
const video _chat _provider _id = Number . parseInt ( $ ( "#id_realm_video_chat_provider" ) . val ( ) , 10 ) ;
const jitsi _meet _id = page _params . realm _available _video _chat _providers . jitsi _meet . id ;
return video _chat _provider _id === jitsi _meet _id ;
}
function get _jitsi _server _url _setting _value ( $input _elem , for _api _data = true ) {
// If the video chat provider dropdown is not set to Jitsi, we return
// `realm_jitsi_server_url` to indicate that the property remains unchanged.
// This ensures the appropriate state of the save button and prevents the
// addition of the `jitsi_server_url` in the API data.
if ( ! is _video _chat _provider _jitsi _meet ( ) ) {
return page _params . realm _jitsi _server _url ;
}
const select _elem _val = $input _elem . val ( ) ;
if ( select _elem _val === "server_default" ) {
if ( ! for _api _data ) {
return null ;
}
return JSON . stringify ( "default" ) ;
}
const $custom _input _elem = $ ( "#id_realm_jitsi_server_url_custom_input" ) ;
if ( ! for _api _data ) {
return $custom _input _elem . val ( ) ;
}
return JSON . stringify ( $custom _input _elem . val ( ) ) ;
}
function update _jitsi _server _url _custom _input ( dropdown _val ) {
const custom _input = "id_realm_jitsi_server_url_custom_input" ;
change _element _block _display _property ( custom _input , dropdown _val === "custom" ) ;
if ( dropdown _val !== "custom" ) {
return ;
}
const $custom _input _elem = $ ( ` # ${ CSS . escape ( custom _input ) } ` ) ;
$custom _input _elem . val ( page _params . realm _jitsi _server _url ) ;
}
function set _jitsi _server _url _dropdown ( ) {
if ( ! is _video _chat _provider _jitsi _meet ( ) ) {
$ ( "#realm_jitsi_server_url_setting" ) . hide ( ) ;
return ;
}
$ ( "#realm_jitsi_server_url_setting" ) . show ( ) ;
let dropdown _val = "server_default" ;
if ( page _params . realm _jitsi _server _url ) {
dropdown _val = "custom" ;
}
$ ( "#id_realm_jitsi_server_url" ) . val ( dropdown _val ) ;
update _jitsi _server _url _custom _input ( dropdown _val ) ;
}
2018-04-23 14:51:30 +02:00
function set _video _chat _provider _dropdown ( ) {
2019-11-02 00:06:25 +01:00
const chat _provider _id = page _params . realm _video _chat _provider ;
2019-05-09 09:54:38 +02:00
$ ( "#id_realm_video_chat_provider" ) . val ( chat _provider _id ) ;
2023-09-19 18:10:23 +02:00
set _jitsi _server _url _dropdown ( ) ;
2018-04-23 14:51:30 +02:00
}
2021-04-27 21:58:19 +02:00
function set _giphy _rating _dropdown ( ) {
const rating _id = page _params . realm _giphy _rating ;
$ ( "#id_realm_giphy_rating" ) . val ( rating _id ) ;
}
2022-04-12 09:56:58 +02:00
function update _message _edit _sub _settings ( is _checked ) {
2022-08-19 16:14:15 +02:00
settings _ui . disable _sub _setting _onchange (
is _checked ,
"id_realm_message_content_edit_limit_seconds" ,
true ,
) ;
2022-04-12 09:56:58 +02:00
settings _ui . disable _sub _setting _onchange (
is _checked ,
"id_realm_message_content_edit_limit_minutes" ,
true ,
) ;
}
2022-09-02 13:58:03 +02:00
function update _custom _value _input ( property _name ) {
const $dropdown _elem = $ ( ` #id_ ${ CSS . escape ( property _name ) } ` ) ;
const custom _input _elem _id = $dropdown _elem
. parent ( )
2023-01-16 10:46:45 +01:00
. find ( ".time-limit-custom-input" )
2022-09-02 13:58:03 +02:00
. attr ( "id" ) ;
const show _custom _limit _input = $dropdown _elem . val ( ) === "custom_period" ;
change _element _block _display _property ( custom _input _elem _id , show _custom _limit _input ) ;
if ( show _custom _limit _input ) {
$ ( ` # ${ CSS . escape ( custom _input _elem _id ) } ` ) . val (
get _realm _time _limits _in _minutes ( property _name ) ,
) ;
}
}
2022-09-02 13:07:11 +02:00
function get _time _limit _dropdown _setting _value ( property _name ) {
if ( page _params [ property _name ] === null ) {
return "any_time" ;
}
const valid _limit _values = settings _config . time _limit _dropdown _values . map ( ( x ) => x . value ) ;
if ( valid _limit _values . includes ( page _params [ property _name ] ) ) {
return page _params [ property _name ] . toString ( ) ;
}
return "custom_period" ;
}
2022-09-08 12:19:16 +02:00
function set _time _limit _setting ( property _name ) {
const dropdown _elem _val = get _time _limit _dropdown _setting _value ( property _name ) ;
$ ( ` #id_ ${ CSS . escape ( property _name ) } ` ) . val ( dropdown _elem _val ) ;
const $custom _input = $ ( ` #id_ ${ CSS . escape ( property _name ) } ` )
. parent ( )
2023-01-16 10:46:45 +01:00
. find ( ".time-limit-custom-input" ) ;
2022-09-08 12:19:16 +02:00
$custom _input . val ( get _realm _time _limits _in _minutes ( property _name ) ) ;
2020-07-15 00:34:28 +02:00
change _element _block _display _property (
2022-09-08 12:19:16 +02:00
$custom _input . attr ( "id" ) ,
2022-09-02 13:07:11 +02:00
dropdown _elem _val === "custom_period" ,
2020-07-15 00:34:28 +02:00
) ;
2018-04-02 11:18:40 +02:00
}
2022-09-08 12:19:16 +02:00
function set _msg _edit _limit _dropdown ( ) {
set _time _limit _setting ( "realm_message_content_edit_limit_seconds" ) ;
}
2022-12-22 19:14:23 +01:00
function message _move _limit _setting _enabled ( related _setting _name ) {
const setting _value = Number . parseInt ( $ ( ` #id_ ${ CSS . escape ( related _setting _name ) } ` ) . val ( ) , 10 ) ;
let settings _options ;
if ( related _setting _name === "realm_edit_topic_policy" ) {
settings _options = settings _config . edit _topic _policy _values ;
} else {
settings _options = settings _config . move _messages _between _streams _policy _values ;
}
if ( setting _value === settings _options . by _admins _only . code ) {
return false ;
}
if ( setting _value === settings _options . by _moderators _only . code ) {
return false ;
}
if ( setting _value === settings _options . nobody . code ) {
return false ;
}
return true ;
}
function enable _or _disable _related _message _move _time _limit _setting ( setting _name , disable _setting ) {
const $setting _elem = $ ( ` #id_ ${ CSS . escape ( setting _name ) } ` ) ;
const $custom _input _elem = $setting _elem . parent ( ) . find ( ".time-limit-custom-input" ) ;
settings _ui . disable _sub _setting _onchange ( disable _setting , $setting _elem . attr ( "id" ) , true ) ;
settings _ui . disable _sub _setting _onchange ( disable _setting , $custom _input _elem . attr ( "id" ) , true ) ;
}
function set _msg _move _limit _setting ( property _name ) {
set _time _limit _setting ( property _name ) ;
2023-01-30 12:15:36 +01:00
let disable _setting ;
if ( property _name === "realm_move_messages_within_stream_limit_seconds" ) {
disable _setting = message _move _limit _setting _enabled ( "realm_edit_topic_policy" ) ;
} else {
disable _setting = message _move _limit _setting _enabled (
"realm_move_messages_between_streams_policy" ,
) ;
}
2022-12-22 19:14:23 +01:00
enable _or _disable _related _message _move _time _limit _setting ( property _name , disable _setting ) ;
}
2022-08-18 16:14:05 +02:00
function message _delete _limit _setting _enabled ( setting _value ) {
2021-06-23 12:53:38 +02:00
// This function is used to check whether the time-limit setting
// should be enabled. The setting is disabled when delete_own_message_policy
// is set to 'admins only' as admins can delete messages irrespective of
// time limit.
2022-08-18 16:14:05 +02:00
if ( setting _value === settings _config . common _message _policy _values . by _admins _only . code ) {
2021-06-23 12:53:38 +02:00
return false ;
}
return true ;
}
2022-08-18 16:14:05 +02:00
function set _delete _own _message _policy _dropdown ( setting _value ) {
$ ( "#id_realm_delete_own_message_policy" ) . val ( setting _value ) ;
2021-06-08 13:45:14 +02:00
settings _ui . disable _sub _setting _onchange (
2022-08-18 16:14:05 +02:00
message _delete _limit _setting _enabled ( setting _value ) ,
2022-08-19 16:47:26 +02:00
"id_realm_message_content_delete_limit_seconds" ,
2021-06-08 13:45:14 +02:00
true ,
) ;
2022-09-02 13:07:11 +02:00
const limit _setting _dropdown _value = get _time _limit _dropdown _setting _value (
"realm_message_content_delete_limit_seconds" ,
) ;
if ( limit _setting _dropdown _value === "custom_period" ) {
2021-06-08 13:45:14 +02:00
settings _ui . disable _sub _setting _onchange (
2022-08-18 16:14:05 +02:00
message _delete _limit _setting _enabled ( setting _value ) ,
2021-06-08 13:45:14 +02:00
"id_realm_message_content_delete_limit_minutes" ,
true ,
) ;
}
}
2017-11-26 09:12:10 +01:00
function set _msg _delete _limit _dropdown ( ) {
2022-09-08 12:19:16 +02:00
set _time _limit _setting ( "realm_message_content_delete_limit_seconds" ) ;
2017-11-26 09:12:10 +01:00
}
2022-11-04 11:11:33 +01:00
function get _message _retention _setting _value ( $input _elem , for _api _data = true ) {
const select _elem _val = $input _elem . val ( ) ;
2022-11-04 11:11:33 +01:00
if ( select _elem _val === "unlimited" ) {
2022-11-04 11:11:33 +01:00
if ( ! for _api _data ) {
return settings _config . retain _message _forever ;
}
return JSON . stringify ( "unlimited" ) ;
}
2022-10-18 11:36:52 +02:00
if ( select _elem _val === "realm_default" ) {
if ( ! for _api _data ) {
return null ;
}
return JSON . stringify ( "realm_default" ) ;
}
2022-11-04 11:11:33 +01:00
const $custom _input = $input _elem . parent ( ) . find ( ".message-retention-setting-custom-input" ) ;
if ( $custom _input . val ( ) . length === 0 ) {
return settings _config . retain _message _forever ;
}
2023-01-20 09:20:29 +01:00
return Number . parseInt ( Number ( $custom _input . val ( ) ) , 10 ) ;
2022-11-04 11:11:33 +01:00
}
function get _dropdown _value _for _message _retention _setting ( setting _value ) {
if ( setting _value === settings _config . retain _message _forever ) {
2022-11-04 11:11:33 +01:00
return "unlimited" ;
2022-11-04 11:11:33 +01:00
}
2022-10-18 11:03:09 +02:00
if ( setting _value === null ) {
return "realm_default" ;
}
2022-11-04 11:11:33 +01:00
return "custom_period" ;
2022-11-04 11:11:33 +01:00
}
2022-10-18 11:03:09 +02:00
export function set _message _retention _setting _dropdown ( sub ) {
let property _name = "realm_message_retention_days" ;
if ( sub !== undefined ) {
property _name = "message_retention_days" ;
}
const setting _value = get _property _value ( property _name , false , sub ) ;
2022-11-04 11:11:33 +01:00
const dropdown _val = get _dropdown _value _for _message _retention _setting ( setting _value ) ;
2022-11-04 11:11:33 +01:00
2022-11-04 11:11:33 +01:00
const $dropdown _elem = $ ( ` #id_ ${ CSS . escape ( property _name ) } ` ) ;
$dropdown _elem . val ( dropdown _val ) ;
2022-11-04 11:11:33 +01:00
2022-11-04 11:11:33 +01:00
const $custom _input _elem = $dropdown _elem
. parent ( )
. find ( ".message-retention-setting-custom-input" )
. val ( "" ) ;
if ( dropdown _val === "custom_period" ) {
$custom _input _elem . val ( setting _value ) ;
2020-06-21 11:35:02 +02:00
}
2022-11-04 11:11:33 +01:00
change _element _block _display _property (
$custom _input _elem . attr ( "id" ) ,
dropdown _val === "custom_period" ,
) ;
2020-05-07 13:19:54 +02:00
}
2018-04-05 00:54:31 +02:00
function set _org _join _restrictions _dropdown ( ) {
2019-11-02 00:06:25 +01:00
const value = get _property _value ( "realm_org_join_restrictions" ) ;
2018-04-05 00:54:31 +02:00
$ ( "#id_realm_org_join_restrictions" ) . val ( value ) ;
2020-07-15 00:34:28 +02:00
change _element _block _display _property (
"allowed_domains_label" ,
value === "only_selected_domain" ,
) ;
2018-04-05 00:54:31 +02:00
}
2023-01-02 20:50:23 +01:00
function set _message _content _in _email _notifications _visibility ( ) {
2020-02-03 13:03:53 +01:00
change _element _block _display _property (
2020-07-15 01:29:15 +02:00
"message_content_in_email_notifications_label" ,
2020-07-15 00:34:28 +02:00
page _params . realm _message _content _allowed _in _email _notifications ,
) ;
2019-01-14 14:04:08 +01:00
}
2019-05-08 08:11:30 +02:00
function set _digest _emails _weekday _visibility ( ) {
2020-07-15 00:34:28 +02:00
change _element _block _display _property (
"id_realm_digest_weekday" ,
page _params . realm _digest _emails _enabled ,
) ;
2019-05-08 08:11:30 +02:00
}
2021-11-19 10:29:39 +01:00
function set _create _web _public _stream _dropdown _visibility ( ) {
change _element _block _display _property (
"id_realm_create_web_public_stream_policy" ,
2022-05-26 11:43:42 +02:00
page _params . server _web _public _streams _enabled &&
page _params . zulip _plan _is _not _limited &&
page _params . realm _enable _spectator _access ,
2021-11-19 10:29:39 +01:00
) ;
}
2021-07-20 14:51:48 +02:00
export function populate _realm _domains _label ( realm _domains ) {
2017-04-08 18:13:39 +02:00
if ( ! meta . loaded ) {
return ;
}
2020-07-15 00:34:28 +02:00
const domains _list = realm _domains . map ( ( realm _domain ) =>
realm _domain . allow _subdomains ? "*." + realm _domain . domain : realm _domain . domain ,
js: Convert _.map(a, …) to a.map(…).
And convert the corresponding function expressions to arrow style
while we’re here.
import * as babelParser from "recast/parsers/babel";
import * as recast from "recast";
import * as tsParser from "recast/parsers/typescript";
import { builders as b, namedTypes as n } from "ast-types";
import K from "ast-types/gen/kinds";
import fs from "fs";
import path from "path";
import process from "process";
const checkExpression = (node: n.Node): node is K.ExpressionKind =>
n.Expression.check(node);
for (const file of process.argv.slice(2)) {
console.log("Parsing", file);
const ast = recast.parse(fs.readFileSync(file, { encoding: "utf8" }), {
parser: path.extname(file) === ".ts" ? tsParser : babelParser,
});
let changed = false;
recast.visit(ast, {
visitCallExpression(path) {
const { callee, arguments: args } = path.node;
if (
n.MemberExpression.check(callee) &&
!callee.computed &&
n.Identifier.check(callee.object) &&
callee.object.name === "_" &&
n.Identifier.check(callee.property) &&
callee.property.name === "map" &&
args.length === 2 &&
checkExpression(args[0]) &&
checkExpression(args[1])
) {
const [arr, fn] = args;
path.replace(
b.callExpression(b.memberExpression(arr, b.identifier("map")), [
n.FunctionExpression.check(fn) ||
n.ArrowFunctionExpression.check(fn)
? b.arrowFunctionExpression(
fn.params,
n.BlockStatement.check(fn.body) &&
fn.body.body.length === 1 &&
n.ReturnStatement.check(fn.body.body[0])
? fn.body.body[0].argument || b.identifier("undefined")
: fn.body
)
: fn,
])
);
changed = true;
}
this.traverse(path);
},
});
if (changed) {
console.log("Writing", file);
fs.writeFileSync(file, recast.print(ast).code, { encoding: "utf8" });
}
}
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-08 02:43:49 +01:00
) ;
2020-07-15 01:29:15 +02:00
let domains = domains _list . join ( ", " ) ;
2017-04-08 18:13:39 +02:00
if ( domains . length === 0 ) {
2021-04-13 06:51:54 +02:00
domains = $t ( { defaultMessage : "None" } ) ;
2017-04-08 18:13:39 +02:00
}
2021-04-13 06:51:54 +02:00
$ ( "#allowed_domains_label" ) . text ( $t ( { defaultMessage : "Allowed domains: {domains}" } , { domains } ) ) ;
2021-02-28 01:20:46 +01:00
}
2019-04-07 18:56:32 +02:00
function sort _object _by _key ( obj ) {
2020-02-09 04:45:48 +01:00
const keys = Object . keys ( obj ) . sort ( ) ;
2019-11-02 00:06:25 +01:00
const new _obj = { } ;
js: Automatically convert _.each to for…of.
This commit was automatically generated by the following script,
followed by lint --fix and a few small manual lint-related cleanups.
import * as babelParser from "recast/parsers/babel";
import * as recast from "recast";
import * as tsParser from "recast/parsers/typescript";
import { builders as b, namedTypes as n } from "ast-types";
import { Context } from "ast-types/lib/path-visitor";
import K from "ast-types/gen/kinds";
import { NodePath } from "ast-types/lib/node-path";
import assert from "assert";
import fs from "fs";
import path from "path";
import process from "process";
const checkExpression = (node: n.Node): node is K.ExpressionKind =>
n.Expression.check(node);
const checkStatement = (node: n.Node): node is K.StatementKind =>
n.Statement.check(node);
for (const file of process.argv.slice(2)) {
console.log("Parsing", file);
const ast = recast.parse(fs.readFileSync(file, { encoding: "utf8" }), {
parser: path.extname(file) === ".ts" ? tsParser : babelParser,
});
let changed = false;
let inLoop = false;
let replaceReturn = false;
const visitLoop = (...args: string[]) =>
function(this: Context, path: NodePath) {
for (const arg of args) {
this.visit(path.get(arg));
}
const old = { inLoop };
inLoop = true;
this.visit(path.get("body"));
inLoop = old.inLoop;
return false;
};
recast.visit(ast, {
visitDoWhileStatement: visitLoop("test"),
visitExpressionStatement(path) {
const { expression, comments } = path.node;
let valueOnly;
if (
n.CallExpression.check(expression) &&
n.MemberExpression.check(expression.callee) &&
!expression.callee.computed &&
n.Identifier.check(expression.callee.object) &&
expression.callee.object.name === "_" &&
n.Identifier.check(expression.callee.property) &&
["each", "forEach"].includes(expression.callee.property.name) &&
[2, 3].includes(expression.arguments.length) &&
checkExpression(expression.arguments[0]) &&
(n.FunctionExpression.check(expression.arguments[1]) ||
n.ArrowFunctionExpression.check(expression.arguments[1])) &&
[1, 2].includes(expression.arguments[1].params.length) &&
n.Identifier.check(expression.arguments[1].params[0]) &&
((valueOnly = expression.arguments[1].params[1] === undefined) ||
n.Identifier.check(expression.arguments[1].params[1])) &&
(expression.arguments[2] === undefined ||
n.ThisExpression.check(expression.arguments[2]))
) {
const old = { inLoop, replaceReturn };
inLoop = false;
replaceReturn = true;
this.visit(
path
.get("expression")
.get("arguments")
.get(1)
.get("body")
);
inLoop = old.inLoop;
replaceReturn = old.replaceReturn;
const [right, { body, params }] = expression.arguments;
const loop = b.forOfStatement(
b.variableDeclaration("let", [
b.variableDeclarator(
valueOnly ? params[0] : b.arrayPattern([params[1], params[0]])
),
]),
valueOnly
? right
: b.callExpression(
b.memberExpression(right, b.identifier("entries")),
[]
),
checkStatement(body) ? body : b.expressionStatement(body)
);
loop.comments = comments;
path.replace(loop);
changed = true;
}
this.traverse(path);
},
visitForStatement: visitLoop("init", "test", "update"),
visitForInStatement: visitLoop("left", "right"),
visitForOfStatement: visitLoop("left", "right"),
visitFunction(path) {
this.visit(path.get("params"));
const old = { replaceReturn };
replaceReturn = false;
this.visit(path.get("body"));
replaceReturn = old.replaceReturn;
return false;
},
visitReturnStatement(path) {
if (replaceReturn) {
assert(!inLoop); // could use labeled continue if this ever fires
const { argument, comments } = path.node;
if (argument === null) {
const s = b.continueStatement();
s.comments = comments;
path.replace(s);
} else {
const s = b.expressionStatement(argument);
s.comments = comments;
path.replace(s, b.continueStatement());
}
return false;
}
this.traverse(path);
},
visitWhileStatement: visitLoop("test"),
});
if (changed) {
console.log("Writing", file);
fs.writeFileSync(file, recast.print(ast).code, { encoding: "utf8" });
}
}
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-06 06:19:47 +01:00
for ( const key of keys ) {
2019-04-07 18:56:32 +02:00
new _obj [ key ] = obj [ key ] ;
js: Automatically convert _.each to for…of.
This commit was automatically generated by the following script,
followed by lint --fix and a few small manual lint-related cleanups.
import * as babelParser from "recast/parsers/babel";
import * as recast from "recast";
import * as tsParser from "recast/parsers/typescript";
import { builders as b, namedTypes as n } from "ast-types";
import { Context } from "ast-types/lib/path-visitor";
import K from "ast-types/gen/kinds";
import { NodePath } from "ast-types/lib/node-path";
import assert from "assert";
import fs from "fs";
import path from "path";
import process from "process";
const checkExpression = (node: n.Node): node is K.ExpressionKind =>
n.Expression.check(node);
const checkStatement = (node: n.Node): node is K.StatementKind =>
n.Statement.check(node);
for (const file of process.argv.slice(2)) {
console.log("Parsing", file);
const ast = recast.parse(fs.readFileSync(file, { encoding: "utf8" }), {
parser: path.extname(file) === ".ts" ? tsParser : babelParser,
});
let changed = false;
let inLoop = false;
let replaceReturn = false;
const visitLoop = (...args: string[]) =>
function(this: Context, path: NodePath) {
for (const arg of args) {
this.visit(path.get(arg));
}
const old = { inLoop };
inLoop = true;
this.visit(path.get("body"));
inLoop = old.inLoop;
return false;
};
recast.visit(ast, {
visitDoWhileStatement: visitLoop("test"),
visitExpressionStatement(path) {
const { expression, comments } = path.node;
let valueOnly;
if (
n.CallExpression.check(expression) &&
n.MemberExpression.check(expression.callee) &&
!expression.callee.computed &&
n.Identifier.check(expression.callee.object) &&
expression.callee.object.name === "_" &&
n.Identifier.check(expression.callee.property) &&
["each", "forEach"].includes(expression.callee.property.name) &&
[2, 3].includes(expression.arguments.length) &&
checkExpression(expression.arguments[0]) &&
(n.FunctionExpression.check(expression.arguments[1]) ||
n.ArrowFunctionExpression.check(expression.arguments[1])) &&
[1, 2].includes(expression.arguments[1].params.length) &&
n.Identifier.check(expression.arguments[1].params[0]) &&
((valueOnly = expression.arguments[1].params[1] === undefined) ||
n.Identifier.check(expression.arguments[1].params[1])) &&
(expression.arguments[2] === undefined ||
n.ThisExpression.check(expression.arguments[2]))
) {
const old = { inLoop, replaceReturn };
inLoop = false;
replaceReturn = true;
this.visit(
path
.get("expression")
.get("arguments")
.get(1)
.get("body")
);
inLoop = old.inLoop;
replaceReturn = old.replaceReturn;
const [right, { body, params }] = expression.arguments;
const loop = b.forOfStatement(
b.variableDeclaration("let", [
b.variableDeclarator(
valueOnly ? params[0] : b.arrayPattern([params[1], params[0]])
),
]),
valueOnly
? right
: b.callExpression(
b.memberExpression(right, b.identifier("entries")),
[]
),
checkStatement(body) ? body : b.expressionStatement(body)
);
loop.comments = comments;
path.replace(loop);
changed = true;
}
this.traverse(path);
},
visitForStatement: visitLoop("init", "test", "update"),
visitForInStatement: visitLoop("left", "right"),
visitForOfStatement: visitLoop("left", "right"),
visitFunction(path) {
this.visit(path.get("params"));
const old = { replaceReturn };
replaceReturn = false;
this.visit(path.get("body"));
replaceReturn = old.replaceReturn;
return false;
},
visitReturnStatement(path) {
if (replaceReturn) {
assert(!inLoop); // could use labeled continue if this ever fires
const { argument, comments } = path.node;
if (argument === null) {
const s = b.continueStatement();
s.comments = comments;
path.replace(s);
} else {
const s = b.expressionStatement(argument);
s.comments = comments;
path.replace(s, b.continueStatement());
}
return false;
}
this.traverse(path);
},
visitWhileStatement: visitLoop("test"),
});
if (changed) {
console.log("Writing", file);
fs.writeFileSync(file, recast.print(ast).code, { encoding: "utf8" });
}
}
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-06 06:19:47 +01:00
}
2019-04-07 18:56:32 +02:00
return new _obj ;
}
2021-02-28 01:20:46 +01:00
2023-01-20 18:29:34 +01:00
function can _configure _auth _methods ( ) {
if ( settings _data . user _email _not _configured ( ) ) {
return false ;
}
if ( page _params . is _owner ) {
return true ;
}
return false ;
}
2021-02-28 01:20:46 +01:00
export function populate _auth _methods ( auth _methods ) {
2017-04-08 18:13:39 +02:00
if ( ! meta . loaded ) {
return ;
}
2022-07-07 10:14:13 +02:00
const $auth _methods _list = $ ( "#id_realm_authentication_methods" ) . expectOne ( ) ;
2019-04-07 18:56:32 +02:00
auth _methods = sort _object _by _key ( auth _methods ) ;
2019-11-02 00:06:25 +01:00
let rendered _auth _method _rows = "" ;
2020-02-06 04:27:31 +01:00
for ( const [ auth _method , value ] of Object . entries ( auth _methods ) ) {
2019-07-09 21:24:00 +02:00
rendered _auth _method _rows += render _settings _admin _auth _methods _list ( {
2019-04-06 08:43:34 +02:00
method : auth _method ,
enabled : value ,
2023-01-20 18:29:34 +01:00
disable _configure _auth _method : ! can _configure _auth _methods ( ) ,
2022-07-07 10:12:16 +02:00
// The negated character class regexp serves as an allowlist - the replace() will
// remove *all* symbols *but* digits (\d) and lowecase letters (a-z),
// so that we can make assumptions on this string elsewhere in the code.
// As a result, the only two "incoming" assumptions on the auth method name are:
// 1) It contains at least one allowed symbol
// 2) No two auth method names are identical after this allowlist filtering
2023-05-11 21:49:10 +02:00
prefix : "id_authmethod" + auth _method . toLowerCase ( ) . replaceAll ( /[^\da-z]/g , "" ) + "_" ,
2019-04-06 08:43:34 +02:00
} ) ;
2020-02-06 04:27:31 +01:00
}
2022-07-07 10:14:13 +02:00
$auth _methods _list . html ( rendered _auth _method _rows ) ;
2021-02-28 01:20:46 +01:00
}
2017-04-08 18:13:39 +02:00
2018-04-01 08:56:18 +02:00
function update _dependent _subsettings ( property _name ) {
js: Convert a.indexOf(…) !== -1 to a.includes(…).
Babel polyfills this for us for Internet Explorer.
import * as babelParser from "recast/parsers/babel";
import * as recast from "recast";
import * as tsParser from "recast/parsers/typescript";
import { builders as b, namedTypes as n } from "ast-types";
import K from "ast-types/gen/kinds";
import fs from "fs";
import path from "path";
import process from "process";
const checkExpression = (node: n.Node): node is K.ExpressionKind =>
n.Expression.check(node);
for (const file of process.argv.slice(2)) {
console.log("Parsing", file);
const ast = recast.parse(fs.readFileSync(file, { encoding: "utf8" }), {
parser: path.extname(file) === ".ts" ? tsParser : babelParser,
});
let changed = false;
recast.visit(ast, {
visitBinaryExpression(path) {
const { operator, left, right } = path.node;
if (
n.CallExpression.check(left) &&
n.MemberExpression.check(left.callee) &&
!left.callee.computed &&
n.Identifier.check(left.callee.property) &&
left.callee.property.name === "indexOf" &&
left.arguments.length === 1 &&
checkExpression(left.arguments[0]) &&
((["===", "!==", "==", "!=", ">", "<="].includes(operator) &&
n.UnaryExpression.check(right) &&
right.operator == "-" &&
n.Literal.check(right.argument) &&
right.argument.value === 1) ||
([">=", "<"].includes(operator) &&
n.Literal.check(right) &&
right.value === 0))
) {
const test = b.callExpression(
b.memberExpression(left.callee.object, b.identifier("includes")),
[left.arguments[0]]
);
path.replace(
["!==", "!=", ">", ">="].includes(operator)
? test
: b.unaryExpression("!", test)
);
changed = true;
}
this.traverse(path);
},
});
if (changed) {
console.log("Writing", file);
fs.writeFileSync(file, recast.print(ast).code, { encoding: "utf8" });
}
}
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-08 04:55:06 +01:00
if ( simple _dropdown _properties . includes ( property _name ) ) {
2020-02-03 12:40:36 +01:00
set _property _dropdown _value ( property _name ) ;
2021-05-09 23:36:58 +02:00
return ;
}
switch ( property _name ) {
2022-04-12 09:56:58 +02:00
case "realm_allow_message_editing" :
update _message _edit _sub _settings ( page _params . realm _allow _message _editing ) ;
break ;
2021-06-08 13:45:14 +02:00
case "realm_delete_own_message_policy" :
2022-08-18 16:14:05 +02:00
set _delete _own _message _policy _dropdown ( page _params . realm _delete _own _message _policy ) ;
2021-06-08 13:45:14 +02:00
break ;
2021-05-09 23:36:58 +02:00
case "realm_org_join_restrictions" :
set _org _join _restrictions _dropdown ( ) ;
break ;
case "realm_message_content_allowed_in_email_notifications" :
2023-01-02 20:50:23 +01:00
set _message _content _in _email _notifications _visibility ( ) ;
2021-05-09 23:36:58 +02:00
break ;
case "realm_digest_emails_enabled" :
2021-08-26 13:04:03 +02:00
settings _notifications . set _enable _digest _emails _visibility (
2021-09-30 12:00:57 +02:00
settings _notifications . user _settings _panel ,
2021-08-26 13:04:03 +02:00
) ;
2021-09-16 12:47:12 +02:00
settings _notifications . set _enable _digest _emails _visibility (
2021-09-30 12:00:57 +02:00
settings _realm _user _settings _defaults . realm _default _settings _panel ,
2021-09-16 12:47:12 +02:00
) ;
2021-05-09 23:36:58 +02:00
set _digest _emails _weekday _visibility ( ) ;
break ;
2021-11-19 10:29:39 +01:00
case "realm_enable_spectator_access" :
set _create _web _public _stream _dropdown _visibility ( ) ;
break ;
2018-03-29 12:52:57 +02:00
}
2018-04-01 08:49:10 +02:00
}
2018-03-29 12:52:57 +02:00
2021-02-28 01:20:46 +01:00
export let default _code _language _widget = null ;
export let notifications _stream _widget = null ;
export let signup _notifications _stream _widget = null ;
2023-08-03 16:06:40 +02:00
export let create _multiuse _invite _group _widget = null ;
2023-10-04 03:37:14 +02:00
export let can _remove _subscribers _group _widget = null ;
2021-02-28 01:38:10 +01:00
2022-12-29 10:59:51 +01:00
export function get _widget _for _dropdown _list _settings ( property _name ) {
switch ( property _name ) {
case "realm_notifications_stream_id" :
return notifications _stream _widget ;
case "realm_signup_notifications_stream_id" :
return signup _notifications _stream _widget ;
case "realm_default_code_block_language" :
return default _code _language _widget ;
2023-08-03 16:06:40 +02:00
case "realm_create_multiuse_invite_group" :
return create _multiuse _invite _group _widget ;
2023-07-12 12:57:57 +02:00
case "can_remove_subscribers_group" :
2023-10-04 03:37:14 +02:00
return can _remove _subscribers _group _widget ;
2022-12-29 10:59:51 +01:00
default :
2023-04-24 15:57:45 +02:00
blueslip . error ( "No dropdown list widget for property" , { property _name } ) ;
2022-12-29 10:59:51 +01:00
return null ;
}
}
2023-10-04 03:37:14 +02:00
export function set _can _remove _subscribers _group _widget ( widget ) {
can _remove _subscribers _group _widget = widget ;
}
2022-12-29 10:59:51 +01:00
export function set _dropdown _list _widget _setting _value ( property _name , value ) {
const widget = get _widget _for _dropdown _list _settings ( property _name ) ;
widget . render ( value ) ;
}
2023-07-28 12:01:38 +02:00
export function get _dropdown _list _widget _setting _value ( $input _elem ) {
2022-12-29 10:59:51 +01:00
const widget _name = extract _property _name ( $input _elem ) ;
const setting _widget = get _widget _for _dropdown _list _settings ( widget _name ) ;
const setting _value _type = $input _elem . attr ( "data-setting-value-type" ) ;
if ( setting _value _type === "number" ) {
return Number . parseInt ( setting _widget . value ( ) , 10 ) ;
}
2023-07-28 12:01:38 +02:00
return setting _widget . value ( ) ;
2022-12-29 10:59:51 +01:00
}
2022-10-18 11:56:03 +02:00
export function discard _property _element _changes ( elem , for _realm _default _settings , sub ) {
2022-01-25 11:36:19 +01:00
const $elem = $ ( elem ) ;
const property _name = extract _property _name ( $elem , for _realm _default _settings ) ;
2022-10-18 11:56:03 +02:00
const property _value = get _property _value ( property _name , for _realm _default _settings , sub ) ;
2018-03-29 12:58:35 +02:00
2021-05-09 23:36:58 +02:00
switch ( property _name ) {
2023-09-07 07:53:50 +02:00
case "notification_sound" :
notifications . update _notification _sound _source (
$ ( "#realm-default-notification-sound-audio" ) ,
{
notification _sound : property _value ,
} ,
) ;
set _input _element _value ( $elem , property _value ) ;
break ;
2021-05-09 23:36:58 +02:00
case "realm_authentication_methods" :
populate _auth _methods ( property _value ) ;
break ;
case "realm_notifications_stream_id" :
case "realm_signup_notifications_stream_id" :
case "realm_default_code_block_language" :
2023-07-12 12:57:57 +02:00
case "can_remove_subscribers_group" :
2023-08-03 16:06:40 +02:00
case "realm_create_multiuse_invite_group" :
2022-12-29 10:59:51 +01:00
set _dropdown _list _widget _setting _value ( property _name , property _value ) ;
2021-05-09 23:36:58 +02:00
break ;
2022-05-03 08:06:40 +02:00
case "realm_default_language" :
$ ( "#org-notifications .language_selection_widget .language_selection_button span" ) . attr (
"data-language-code" ,
property _value ,
) ;
$ ( "#org-notifications .language_selection_widget .language_selection_button span" ) . text (
get _language _name ( property _value ) ,
) ;
break ;
2021-09-28 09:09:52 +02:00
case "emojiset" :
2022-08-12 22:41:06 +02:00
case "user_list_style" :
2022-10-18 11:56:03 +02:00
case "stream_privacy" :
2022-08-12 22:41:06 +02:00
// Because this widget has a radio button structure, it
// needs custom reset code.
2022-09-30 16:24:36 +02:00
$elem . find ( ` input[value=' ${ CSS . escape ( property _value ) } '] ` ) . prop ( "checked" , true ) ;
2022-08-12 22:41:06 +02:00
break ;
2021-12-02 15:56:34 +01:00
case "email_notifications_batching_period_seconds" :
case "email_notification_batching_period_edit_minutes" :
settings _notifications . set _notification _batching _ui (
$ ( "#realm-user-default-settings" ) ,
realm _user _settings _defaults . email _notifications _batching _period _seconds ,
) ;
break ;
2022-04-12 17:41:07 +02:00
case "realm_org_type" :
set _input _element _value ( $elem , property _value ) ;
// Remove 'unspecified' option (value=0) from realm_org_type
// dropdown menu options whenever page_params.realm_org_type
// returns another value.
if ( property _value !== 0 ) {
$ ( "#id_realm_org_type option[value=0]" ) . remove ( ) ;
}
break ;
2022-09-02 13:07:11 +02:00
case "realm_message_content_edit_limit_seconds" :
case "realm_message_content_delete_limit_seconds" :
2022-09-08 12:19:16 +02:00
set _time _limit _setting ( property _name ) ;
2022-06-03 19:20:32 +02:00
break ;
2022-12-22 19:14:23 +01:00
case "realm_move_messages_within_stream_limit_seconds" :
2023-01-30 12:15:36 +01:00
case "realm_move_messages_between_streams_limit_seconds" :
2022-12-22 19:14:23 +01:00
set _msg _move _limit _setting ( property _name ) ;
break ;
2023-09-03 05:17:14 +02:00
case "realm_video_chat_provider" :
set _video _chat _provider _dropdown ( ) ;
break ;
2023-09-19 18:10:23 +02:00
case "realm_jitsi_server_url" :
set _jitsi _server _url _dropdown ( ) ;
break ;
2022-11-04 11:11:33 +01:00
case "realm_message_retention_days" :
2022-10-18 11:56:03 +02:00
case "message_retention_days" :
set _message _retention _setting _dropdown ( sub ) ;
2022-11-04 11:11:33 +01:00
break ;
2022-12-12 18:21:08 +01:00
case "realm_waiting_period_threshold" :
set _realm _waiting _period _setting ( ) ;
break ;
2021-05-09 23:36:58 +02:00
default :
if ( property _value !== undefined ) {
2022-01-25 11:36:19 +01:00
set _input _element _value ( $elem , property _value ) ;
2021-05-09 23:36:58 +02:00
} else {
2023-04-24 15:57:45 +02:00
blueslip . error ( "Element refers to unknown property" , { property _name } ) ;
2021-05-09 23:36:58 +02:00
}
2018-03-29 12:58:35 +02:00
}
2018-04-01 08:56:18 +02:00
update _dependent _subsettings ( property _name ) ;
2018-03-29 12:58:35 +02:00
}
2022-10-11 14:20:27 +02:00
export function deactivate _organization ( e ) {
e . preventDefault ( ) ;
e . stopPropagation ( ) ;
function do _deactivate _realm ( ) {
channel . post ( {
url : "/json/realm/deactivate" ,
error ( xhr ) {
ui _report . error ( $t _html ( { defaultMessage : "Failed" } ) , xhr , $ ( "#dialog_error" ) ) ;
} ,
} ) ;
}
const html _body = render _settings _deactivate _realm _modal ( ) ;
dialog _widget . launch ( {
html _heading : $t _html ( { defaultMessage : "Deactivate organization" } ) ,
help _link : "/help/deactivate-your-organization" ,
html _body ,
on _click : do _deactivate _realm ,
close _on _submit : false ,
focus _submit _on _open : true ,
html _submit _button : $t _html ( { defaultMessage : "Confirm" } ) ,
} ) ;
}
2021-02-28 01:20:46 +01:00
export function sync _realm _settings ( property ) {
2022-11-02 19:39:58 +01:00
if ( ! meta . loaded ) {
2018-03-29 13:15:50 +02:00
return ;
}
2021-05-09 23:36:58 +02:00
switch ( property ) {
case "emails_restricted_to_domains" :
case "disallow_disposable_email_addresses" :
property = "org_join_restrictions" ;
break ;
2020-07-15 01:29:15 +02:00
}
2022-01-25 11:36:19 +01:00
const $element = $ ( ` #id_realm_ ${ CSS . escape ( property ) } ` ) ;
if ( $element . length ) {
discard _property _element _changes ( $element ) ;
2018-03-29 13:15:50 +02:00
}
2021-02-28 01:20:46 +01:00
}
2019-03-07 15:18:10 +01:00
2021-02-28 01:20:46 +01:00
export function change _save _button _state ( $element , state ) {
2022-09-15 13:22:47 +02:00
function show _hide _element ( $element , show , fadeout _delay , fadeout _callback ) {
2019-03-07 15:18:10 +01:00
if ( show ) {
2020-07-15 01:29:15 +02:00
$element . removeClass ( "hide" ) . addClass ( ".show" ) . fadeIn ( 300 ) ;
2019-03-07 15:18:10 +01:00
return ;
}
2020-07-02 01:45:54 +02:00
setTimeout ( ( ) => {
2022-09-15 13:22:47 +02:00
$element . fadeOut ( 300 , fadeout _callback ) ;
2019-03-07 15:18:10 +01:00
} , fadeout _delay ) ;
}
2020-07-15 01:29:15 +02:00
const $saveBtn = $element . find ( ".save-button" ) ;
2020-09-01 07:54:40 +02:00
const $textEl = $saveBtn . find ( ".save-discard-widget-button-text" ) ;
2019-03-07 15:18:10 +01:00
2018-03-29 02:02:01 +02:00
if ( state !== "saving" ) {
2020-07-15 01:29:15 +02:00
$saveBtn . removeClass ( "saving" ) ;
2018-03-29 02:02:01 +02:00
}
2019-03-07 15:18:10 +01:00
if ( state === "discarded" ) {
2022-09-15 13:22:47 +02:00
show _hide _element ( $element , false , 0 , ( ) =>
2022-11-03 13:18:42 +01:00
enable _or _disable _save _button ( $element . closest ( ".settings-subsection-parent" ) ) ,
2022-09-15 13:22:47 +02:00
) ;
2019-03-07 15:18:10 +01:00
return ;
}
2019-11-02 00:06:25 +01:00
let button _text ;
let data _status ;
let is _show ;
2021-05-09 23:36:58 +02:00
switch ( state ) {
case "unsaved" :
button _text = $t ( { defaultMessage : "Save changes" } ) ;
data _status = "unsaved" ;
is _show = true ;
$element . find ( ".discard-button" ) . show ( ) ;
break ;
case "saved" :
button _text = $t ( { defaultMessage : "Save changes" } ) ;
data _status = "" ;
is _show = false ;
break ;
case "saving" :
button _text = $t ( { defaultMessage : "Saving" } ) ;
data _status = "saving" ;
is _show = true ;
$element . find ( ".discard-button" ) . hide ( ) ;
$saveBtn . addClass ( "saving" ) ;
break ;
case "failed" :
button _text = $t ( { defaultMessage : "Save changes" } ) ;
data _status = "failed" ;
is _show = true ;
break ;
case "succeeded" :
button _text = $t ( { defaultMessage : "Saved" } ) ;
data _status = "saved" ;
is _show = false ;
break ;
2019-03-09 08:34:53 +01:00
}
2019-03-07 15:18:10 +01:00
$textEl . text ( button _text ) ;
$saveBtn . attr ( "data-status" , data _status ) ;
2022-09-15 13:22:47 +02:00
if ( state === "unsaved" ) {
2022-11-03 13:18:42 +01:00
enable _or _disable _save _button ( $element . closest ( ".settings-subsection-parent" ) ) ;
2022-09-15 13:22:47 +02:00
}
2019-03-07 15:18:10 +01:00
show _hide _element ( $element , is _show , 800 ) ;
2021-02-28 01:20:46 +01:00
}
2018-03-29 02:02:01 +02:00
2022-01-25 11:36:19 +01:00
export function save _organization _settings ( data , $save _button , patch _url ) {
2022-11-03 13:18:42 +01:00
const $subsection _parent = $save _button . closest ( ".settings-subsection-parent" ) ;
2022-01-25 11:36:19 +01:00
const $save _btn _container = $subsection _parent . find ( ".save-button-controls" ) ;
const $failed _alert _elem = $subsection _parent . find ( ".subsection-failed-status p" ) ;
change _save _button _state ( $save _btn _container , "saving" ) ;
2021-09-28 15:56:47 +02:00
channel . patch ( {
2021-09-29 11:25:28 +02:00
url : patch _url ,
2021-09-28 15:56:47 +02:00
data ,
success ( ) {
2022-01-25 11:36:19 +01:00
$failed _alert _elem . hide ( ) ;
change _save _button _state ( $save _btn _container , "succeeded" ) ;
2021-09-28 15:56:47 +02:00
} ,
error ( xhr ) {
2022-01-25 11:36:19 +01:00
change _save _button _state ( $save _btn _container , "failed" ) ;
$save _button . hide ( ) ;
ui _report . error ( $t _html ( { defaultMessage : "Save failed" } ) , xhr , $failed _alert _elem ) ;
2021-09-28 15:56:47 +02:00
} ,
} ) ;
}
2022-01-25 11:36:19 +01:00
function get _input _type ( $input _elem , input _type ) {
2020-05-11 15:11:29 +02:00
if ( [ "boolean" , "string" , "number" ] . includes ( input _type ) ) {
return input _type ;
}
2022-01-25 11:36:19 +01:00
return $input _elem . data ( "setting-widget-type" ) ;
2020-05-11 15:11:29 +02:00
}
2021-02-28 01:20:46 +01:00
export function get _input _element _value ( input _elem , input _type ) {
2022-01-25 11:36:19 +01:00
const $input _elem = $ ( input _elem ) ;
input _type = get _input _type ( $input _elem , input _type ) ;
2021-05-09 23:36:58 +02:00
switch ( input _type ) {
case "boolean" :
2022-01-25 11:36:19 +01:00
return $input _elem . prop ( "checked" ) ;
2021-05-09 23:36:58 +02:00
case "string" :
2022-01-25 11:36:19 +01:00
return $input _elem . val ( ) . trim ( ) ;
2021-05-09 23:36:58 +02:00
case "number" :
2022-01-25 11:36:19 +01:00
return Number . parseInt ( $input _elem . val ( ) . trim ( ) , 10 ) ;
2022-09-30 16:24:36 +02:00
case "radio-group" : {
const selected _val = $input _elem . find ( "input:checked" ) . val ( ) ;
if ( $input _elem . data ( "setting-choice-type" ) === "number" ) {
return Number . parseInt ( selected _val , 10 ) ;
2021-09-28 09:09:52 +02:00
}
2022-09-30 16:24:36 +02:00
return selected _val . trim ( ) ;
}
2022-08-25 10:02:54 +02:00
case "time-limit" :
2022-09-20 16:40:19 +02:00
return get _time _limit _setting _value ( $input _elem ) ;
2023-09-19 18:10:23 +02:00
case "jitsi-server-url-setting" :
return get _jitsi _server _url _setting _value ( $input _elem ) ;
2022-11-04 11:11:33 +01:00
case "message-retention-setting" :
return get _message _retention _setting _value ( $input _elem ) ;
2022-12-29 10:59:51 +01:00
case "dropdown-list-widget" :
return get _dropdown _list _widget _setting _value ( $input _elem ) ;
2021-05-09 23:36:58 +02:00
default :
return undefined ;
2020-03-22 16:13:50 +01:00
}
2021-02-28 01:20:46 +01:00
}
2020-03-22 16:13:50 +01:00
2022-01-25 11:36:19 +01:00
export function set _input _element _value ( $input _elem , value ) {
const input _type = get _input _type ( $input _elem , typeof value ) ;
2020-05-11 15:44:01 +02:00
if ( input _type ) {
2020-07-15 01:29:15 +02:00
if ( input _type === "boolean" ) {
2022-01-25 11:36:19 +01:00
return $input _elem . prop ( "checked" , value ) ;
2021-05-09 23:36:58 +02:00
} else if ( input _type === "string" || input _type === "number" ) {
2022-01-25 11:36:19 +01:00
return $input _elem . val ( value ) ;
2020-05-11 15:44:01 +02:00
}
}
2023-04-24 15:57:45 +02:00
blueslip . error ( "Failed to set value of property" , {
property : extract _property _name ( $input _elem ) ,
} ) ;
2020-09-24 07:50:36 +02:00
return undefined ;
2021-02-28 01:20:46 +01:00
}
2020-05-11 15:44:01 +02:00
2021-02-28 01:20:46 +01:00
export function set _up ( ) {
build _page ( ) ;
maybe _disable _widgets ( ) ;
}
2018-12-08 18:16:37 +01:00
2022-07-07 10:14:13 +02:00
function get _auth _method _list _data ( ) {
2020-04-10 04:43:37 +02:00
const new _auth _methods = { } ;
2022-07-07 10:12:16 +02:00
const $auth _method _rows = $ ( "#id_realm_authentication_methods" ) . find ( "div.method_row" ) ;
2020-04-10 04:43:37 +02:00
2022-01-25 11:36:19 +01:00
for ( const method _row of $auth _method _rows ) {
2020-07-15 00:34:28 +02:00
new _auth _methods [ $ ( method _row ) . data ( "method" ) ] = $ ( method _row )
. find ( "input" )
. prop ( "checked" ) ;
2020-04-10 04:43:37 +02:00
}
return new _auth _methods ;
}
2022-11-27 18:38:48 +01:00
export function parse _time _limit ( $elem ) {
return Math . floor ( Number . parseFloat ( Number ( $elem . val ( ) ) , 10 ) . toFixed ( 1 ) * 60 ) ;
}
2022-09-20 16:40:19 +02:00
function get _time _limit _setting _value ( $input _elem , for _api _data = true ) {
2022-08-25 10:02:54 +02:00
const select _elem _val = $input _elem . val ( ) ;
if ( select _elem _val === "any_time" ) {
2022-09-02 13:07:11 +02:00
// "unlimited" is sent to API when a user wants to set the setting to
// "Any time" and the message_content_edit_limit_seconds field is "null"
// for that case.
if ( ! for _api _data ) {
return null ;
}
2022-08-25 10:02:54 +02:00
return JSON . stringify ( "unlimited" ) ;
}
if ( select _elem _val !== "custom_period" ) {
return Number . parseInt ( select _elem _val , 10 ) ;
}
2023-01-16 10:46:45 +01:00
const $custom _input _elem = $input _elem . parent ( ) . find ( ".time-limit-custom-input" ) ;
2022-09-02 13:07:11 +02:00
if ( $custom _input _elem . val ( ) . length === 0 ) {
// This handles the case where the initial setting value is "Any time" and then
// dropdown is changed to "Custom" where the input box is empty initially and
// thus we do not show the save-discard widget until something is typed in the
// input box.
return null ;
}
2022-12-12 18:21:08 +01:00
if ( $input _elem . attr ( "id" ) === "id_realm_waiting_period_threshold" ) {
// For realm waiting period threshold setting, the custom input element contains
// number of days.
return Number . parseInt ( Number ( $custom _input _elem . val ( ) ) , 10 ) ;
}
2022-09-02 13:07:11 +02:00
return parse _time _limit ( $custom _input _elem ) ;
2022-08-25 10:02:54 +02:00
}
2022-10-18 12:05:56 +02:00
export function check _property _changed ( elem , for _realm _default _settings , sub ) {
2022-01-25 11:36:19 +01:00
const $elem = $ ( elem ) ;
const property _name = extract _property _name ( $elem , for _realm _default _settings ) ;
2022-10-18 11:36:52 +02:00
let current _val = get _property _value ( property _name , for _realm _default _settings , sub ) ;
2022-08-25 15:44:55 +02:00
let proposed _val ;
2020-04-10 04:43:37 +02:00
2021-05-09 23:36:58 +02:00
switch ( property _name ) {
case "realm_authentication_methods" :
current _val = sort _object _by _key ( current _val ) ;
current _val = JSON . stringify ( current _val ) ;
2022-08-25 15:44:55 +02:00
proposed _val = get _auth _method _list _data ( ) ;
proposed _val = JSON . stringify ( proposed _val ) ;
2021-05-09 23:36:58 +02:00
break ;
case "realm_notifications_stream_id" :
case "realm_signup_notifications_stream_id" :
case "realm_default_code_block_language" :
2023-07-12 12:57:57 +02:00
case "can_remove_subscribers_group" :
2023-08-03 16:06:40 +02:00
case "realm_create_multiuse_invite_group" :
2023-07-28 12:01:38 +02:00
proposed _val = get _dropdown _list _widget _setting _value ( $elem ) ;
2021-05-09 23:36:58 +02:00
break ;
2021-12-02 15:56:34 +01:00
case "email_notifications_batching_period_seconds" :
2022-09-20 19:49:30 +02:00
proposed _val = get _time _limit _setting _value ( $elem , false ) ;
2021-12-02 15:56:34 +01:00
break ;
2022-08-25 10:02:54 +02:00
case "realm_message_content_edit_limit_seconds" :
case "realm_message_content_delete_limit_seconds" :
2023-01-30 12:15:36 +01:00
case "realm_move_messages_between_streams_limit_seconds" :
2022-12-22 19:14:23 +01:00
case "realm_move_messages_within_stream_limit_seconds" :
2022-12-12 18:21:08 +01:00
case "realm_waiting_period_threshold" :
2022-09-20 16:40:19 +02:00
proposed _val = get _time _limit _setting _value ( $elem , false ) ;
2022-08-22 12:19:50 +02:00
break ;
2022-11-04 11:11:33 +01:00
case "realm_message_retention_days" :
2022-10-18 11:36:52 +02:00
case "message_retention_days" :
2022-11-04 11:11:33 +01:00
proposed _val = get _message _retention _setting _value ( $elem , false ) ;
break ;
2023-09-19 18:10:23 +02:00
case "realm_jitsi_server_url" :
proposed _val = get _jitsi _server _url _setting _value ( $elem , false ) ;
break ;
2022-05-03 08:06:40 +02:00
case "realm_default_language" :
2022-08-25 15:44:55 +02:00
proposed _val = $ (
2022-05-03 08:06:40 +02:00
"#org-notifications .language_selection_widget .language_selection_button span" ,
) . attr ( "data-language-code" ) ;
break ;
2022-09-30 16:24:36 +02:00
case "emojiset" :
case "user_list_style" :
2022-10-18 12:05:56 +02:00
case "stream_privacy" :
2022-09-30 16:24:36 +02:00
proposed _val = get _input _element _value ( $elem , "radio-group" ) ;
break ;
2021-05-09 23:36:58 +02:00
default :
if ( current _val !== undefined ) {
2022-08-25 15:44:55 +02:00
proposed _val = get _input _element _value ( $elem , typeof current _val ) ;
2021-05-09 23:36:58 +02:00
} else {
2023-04-24 15:57:45 +02:00
blueslip . error ( "Element refers to unknown property" , { property _name } ) ;
2021-05-09 23:36:58 +02:00
}
2020-04-10 04:43:37 +02:00
}
2022-08-25 15:44:55 +02:00
return current _val !== proposed _val ;
2020-04-10 04:43:37 +02:00
}
2023-08-09 22:30:51 +02:00
function switching _to _private ( properties _elements , for _realm _default _settings ) {
for ( const elem of properties _elements ) {
const $elem = $ ( elem ) ;
const property _name = extract _property _name ( $elem , for _realm _default _settings ) ;
if ( property _name !== "stream_privacy" ) {
continue ;
}
const proposed _val = get _input _element _value ( $elem , "radio-group" ) ;
return proposed _val === "invite-only-public-history" || proposed _val === "invite-only" ;
}
return false ;
}
2022-10-18 11:36:52 +02:00
export function save _discard _widget _status _handler ( $subsection , for _realm _default _settings , sub ) {
2022-01-25 11:36:19 +01:00
$subsection . find ( ".subsection-failed-status p" ) . hide ( ) ;
$subsection . find ( ".save-button" ) . show ( ) ;
const properties _elements = get _subsection _property _elements ( $subsection ) ;
2021-01-23 02:36:54 +01:00
const show _change _process _button = properties _elements . some ( ( elem ) =>
2022-10-18 11:36:52 +02:00
check _property _changed ( elem , for _realm _default _settings , sub ) ,
2021-01-23 02:36:54 +01:00
) ;
2020-04-10 04:43:37 +02:00
2022-01-25 11:36:19 +01:00
const $save _btn _controls = $subsection . find ( ".subsection-header .save-button-controls" ) ;
2020-04-10 04:43:37 +02:00
const button _state = show _change _process _button ? "unsaved" : "discarded" ;
2022-01-25 11:36:19 +01:00
change _save _button _state ( $save _btn _controls , button _state ) ;
2023-08-09 22:30:51 +02:00
// If this widget is for a stream, and the stream isn't currently private
// but being changed to private, and the user changing this setting isn't
// subscribed, we show a warning that they won't be able to access the
// stream after making it private unless they subscribe.
if ( ! sub ) {
return ;
}
if (
button _state === "unsaved" &&
! sub . invite _only &&
! sub . subscribed &&
switching _to _private ( properties _elements , for _realm _default _settings )
) {
if ( $ ( "#stream_permission_settings .stream_privacy_warning" ) . length > 0 ) {
return ;
}
const context = {
banner _type : compose _banner . WARNING ,
banner _text : $t ( {
defaultMessage :
"Only subscribers can access or join private streams, so you will lose access to this stream if you convert it to a private stream while not subscribed to it." ,
} ) ,
button _text : $t ( { defaultMessage : "Subscribe" } ) ,
classname : "stream_privacy_warning" ,
stream _id : sub . stream _id ,
} ;
$ ( "#stream_permission_settings .stream-permissions-warning-banner" ) . append (
render _compose _banner ( context ) ,
) ;
} else {
$ ( "#stream_permission_settings .stream-permissions-warning-banner" ) . empty ( ) ;
}
2021-02-28 01:20:46 +01:00
}
2020-04-10 06:30:14 +02:00
2021-02-28 01:20:46 +01:00
export function init _dropdown _widgets ( ) {
2023-07-19 16:14:00 +02:00
const notification _stream _options = ( ) => {
const streams = stream _settings _data . get _streams _for _settings _page ( ) ;
const options = streams . map ( ( stream ) => ( {
name : stream . name ,
unique _id : stream . stream _id ,
stream ,
} ) ) ;
const disabled _option = {
is _setting _disabled : true ,
unique _id : DISABLED _STATE _ID ,
2023-10-03 06:42:01 +02:00
name : $t ( { defaultMessage : "Cannot view stream" } ) ,
2023-07-19 16:14:00 +02:00
} ;
options . unshift ( disabled _option ) ;
return options ;
2020-04-10 09:38:55 +02:00
} ;
2023-07-19 16:14:00 +02:00
notifications _stream _widget = new dropdown _widget . DropdownWidget ( {
2020-12-22 00:37:36 +01:00
widget _name : "realm_notifications_stream_id" ,
2023-07-19 16:14:00 +02:00
get _options : notification _stream _options ,
$events _container : $ ( "#settings_overlay_container #organization-settings" ) ,
item _click _callback ( event , dropdown ) {
dropdown . hide ( ) ;
event . preventDefault ( ) ;
event . stopPropagation ( ) ;
notifications _stream _widget . render ( ) ;
save _discard _widget _status _handler ( $ ( "#org-notifications" ) ) ;
} ,
tippy _props : {
placement : "bottom-start" ,
} ,
default _id : page _params . realm _notifications _stream _id ,
unique _id _type : dropdown _widget . DATA _TYPES . NUMBER ,
2023-08-05 03:46:26 +02:00
show _disabled _if _current _value _not _in _options : true ,
2020-12-22 00:37:36 +01:00
} ) ;
2022-04-28 00:12:57 +02:00
notifications _stream _widget . setup ( ) ;
2023-07-19 16:14:00 +02:00
signup _notifications _stream _widget = new dropdown _widget . DropdownWidget ( {
2020-12-22 00:37:36 +01:00
widget _name : "realm_signup_notifications_stream_id" ,
2023-07-19 16:14:00 +02:00
get _options : notification _stream _options ,
$events _container : $ ( "#settings_overlay_container #organization-settings" ) ,
item _click _callback ( event , dropdown ) {
dropdown . hide ( ) ;
event . preventDefault ( ) ;
event . stopPropagation ( ) ;
signup _notifications _stream _widget . render ( ) ;
save _discard _widget _status _handler ( $ ( "#org-notifications" ) ) ;
} ,
tippy _props : {
placement : "bottom-start" ,
} ,
default _id : page _params . realm _signup _notifications _stream _id ,
unique _id _type : dropdown _widget . DATA _TYPES . NUMBER ,
2023-08-05 03:46:26 +02:00
show _disabled _if _current _value _not _in _options : true ,
2020-12-22 00:37:36 +01:00
} ) ;
2022-04-28 00:12:57 +02:00
signup _notifications _stream _widget . setup ( ) ;
2023-07-19 16:14:00 +02:00
default _code _language _widget = new dropdown _widget . DropdownWidget ( {
2020-07-15 01:29:15 +02:00
widget _name : "realm_default_code_block_language" ,
2023-07-19 16:14:00 +02:00
get _options ( ) {
const options = Object . keys ( pygments _data . langs ) . map ( ( x ) => ( {
name : x ,
unique _id : x ,
} ) ) ;
const disabled _option = {
is _setting _disabled : true ,
unique _id : "" ,
name : $t ( { defaultMessage : "No language set" } ) ,
} ;
options . unshift ( disabled _option ) ;
return options ;
} ,
$events _container : $ ( "#settings_overlay_container #organization-settings" ) ,
default _id : page _params . realm _default _code _block _language ,
unique _id _type : dropdown _widget . DATA _TYPES . STRING ,
tippy _props : {
placement : "bottom-start" ,
} ,
item _click _callback ( event , dropdown ) {
dropdown . hide ( ) ;
event . preventDefault ( ) ;
event . stopPropagation ( ) ;
default _code _language _widget . render ( ) ;
2021-02-28 01:20:46 +01:00
save _discard _widget _status _handler ( $ ( "#org-other-settings" ) ) ;
2020-04-30 13:09:48 +02:00
} ,
2020-04-10 09:38:55 +02:00
} ) ;
2022-04-28 00:12:57 +02:00
default _code _language _widget . setup ( ) ;
2023-08-03 16:06:40 +02:00
create _multiuse _invite _group _widget = new dropdown _widget . DropdownWidget ( {
widget _name : "realm_create_multiuse_invite_group" ,
get _options : ( ) =>
user _groups . get _realm _user _groups _for _dropdown _list _widget (
"create_multiuse_invite_group" ,
) ,
$events _container : $ ( "#settings_overlay_container #organization-permissions" ) ,
item _click _callback ( event , dropdown ) {
dropdown . hide ( ) ;
event . preventDefault ( ) ;
event . stopPropagation ( ) ;
create _multiuse _invite _group _widget . render ( ) ;
save _discard _widget _status _handler ( $ ( "#org-join-settings" ) ) ;
} ,
tippy _props : {
placement : "bottom-start" ,
} ,
default _id : page _params . realm _create _multiuse _invite _group ,
unique _id _type : dropdown _widget . DATA _TYPES . NUMBER ,
on _mount _callback ( dropdown ) {
$ ( dropdown . popper ) . css ( "min-width" , "300px" ) ;
} ,
} ) ;
create _multiuse _invite _group _widget . setup ( ) ;
2021-02-28 01:20:46 +01:00
}
2020-04-10 04:43:37 +02:00
2023-01-20 13:25:32 +01:00
function check _maximum _valid _value ( $custom _input _elem , property _name ) {
let setting _value = Number . parseInt ( $custom _input _elem . val ( ) , 10 ) ;
if (
property _name === "realm_message_content_edit_limit_seconds" ||
property _name === "realm_message_content_delete_limit_seconds" ||
property _name === "email_notifications_batching_period_seconds"
) {
setting _value = parse _time _limit ( $custom _input _elem ) ;
}
return setting _value <= MAX _CUSTOM _TIME _LIMIT _SETTING _VALUE ;
}
2023-09-19 18:10:23 +02:00
function should _disable _save _button _for _jitsi _server _url _setting ( ) {
if ( ! is _video _chat _provider _jitsi _meet ( ) ) {
return false ;
}
const $dropdown _elem = $ ( "#id_realm_jitsi_server_url" ) ;
const $custom _input _elem = $ ( "#id_realm_jitsi_server_url_custom_input" ) ;
2023-09-28 08:54:36 +02:00
return $dropdown _elem . val ( ) === "custom" && ! util . is _valid _url ( $custom _input _elem . val ( ) , true ) ;
2023-09-19 18:10:23 +02:00
}
function should _disable _save _button _for _time _limit _settings ( time _limit _settings ) {
2022-09-02 19:03:01 +02:00
let disable _save _btn = false ;
for ( const setting _elem of time _limit _settings ) {
2023-01-20 13:25:32 +01:00
const $dropdown _elem = $ ( setting _elem ) . find ( "select" ) ;
2023-01-16 10:46:45 +01:00
const $custom _input _elem = $ ( setting _elem ) . find ( ".time-limit-custom-input" ) ;
2022-12-12 18:21:08 +01:00
const custom _input _elem _val = Number . parseInt ( Number ( $custom _input _elem . val ( ) ) , 10 ) ;
2022-09-02 19:03:01 +02:00
2023-01-20 13:25:32 +01:00
const for _realm _default _settings =
$dropdown _elem . closest ( ".settings-section.show" ) . attr ( "id" ) ===
"realm-user-default-settings" ;
const property _name = extract _property _name ( $dropdown _elem , for _realm _default _settings ) ;
2022-09-02 19:03:01 +02:00
disable _save _btn =
2023-01-20 13:25:32 +01:00
$dropdown _elem . val ( ) === "custom_period" &&
( custom _input _elem _val <= 0 ||
Number . isNaN ( custom _input _elem _val ) ||
! check _maximum _valid _value ( $custom _input _elem , property _name ) ) ;
2022-12-12 18:21:08 +01:00
if (
$custom _input _elem . val ( ) === "0" &&
2023-01-20 13:25:32 +01:00
property _name === "realm_waiting_period_threshold"
2022-12-12 18:21:08 +01:00
) {
// 0 is a valid value for realm_waiting_period_threshold setting. We specifically
// check for $custom_input_elem.val() to be "0" and not custom_input_elem_val
// because it is 0 even when custom input box is empty.
disable _save _btn = false ;
}
2022-09-02 19:03:01 +02:00
if ( disable _save _btn ) {
break ;
}
}
2023-09-19 18:10:23 +02:00
return disable _save _btn ;
}
function enable _or _disable _save _button ( $subsection _elem ) {
const time _limit _settings = [ ... $subsection _elem . find ( ".time-limit-setting" ) ] ;
let disable _save _btn = false ;
if ( time _limit _settings . length ) {
disable _save _btn = should _disable _save _button _for _time _limit _settings ( time _limit _settings ) ;
} else if ( $subsection _elem . attr ( "id" ) === "org-other-settings" ) {
disable _save _btn = should _disable _save _button _for _jitsi _server _url _setting ( ) ;
}
2022-09-02 19:03:01 +02:00
$subsection _elem . find ( ".subsection-changes-save button" ) . prop ( "disabled" , disable _save _btn ) ;
}
2022-10-18 12:05:56 +02:00
export function populate _data _for _request ( subsection , for _realm _default _settings , sub ) {
let data = { } ;
2022-11-09 17:54:47 +01:00
const properties _elements = get _subsection _property _elements ( subsection ) ;
for ( const input _elem of properties _elements ) {
const $input _elem = $ ( input _elem ) ;
2022-10-18 12:05:56 +02:00
if ( check _property _changed ( $input _elem , for _realm _default _settings , sub ) ) {
2022-11-09 17:54:47 +01:00
const input _value = get _input _element _value ( $input _elem ) ;
if ( input _value !== undefined ) {
let property _name ;
2022-10-18 12:05:56 +02:00
if ( for _realm _default _settings || sub ) {
2022-11-09 17:54:47 +01:00
property _name = extract _property _name ( $input _elem , for _realm _default _settings ) ;
} else if ( $input _elem . attr ( "id" ) . startsWith ( "id_authmethod" ) ) {
// Authentication Method component IDs include authentication method name
// for uniqueness, anchored to "id_authmethod" prefix, e.g. "id_authmethodapple_<property_name>".
// We need to strip that whole construct down to extract the actual property name.
// The [\da-z]+ part of the regexp covers the auth method name itself.
// We assume it's not an empty string and can contain only digits and lowercase ASCII letters,
// this is ensured by a respective allowlist-based filter in populate_auth_methods().
[ , property _name ] = /^id_authmethod[\da-z]+_(.*)$/ . exec ( $input _elem . attr ( "id" ) ) ;
} else {
[ , property _name ] = /^id_realm_(.*)$/ . exec ( $input _elem . attr ( "id" ) ) ;
}
2022-10-18 12:05:56 +02:00
if ( property _name === "stream_privacy" ) {
data = {
... data ,
2023-10-04 03:28:40 +02:00
... settings _data . get _request _data _for _stream _privacy ( input _value ) ,
2022-10-18 12:05:56 +02:00
} ;
continue ;
}
2022-11-09 17:54:47 +01:00
data [ property _name ] = input _value ;
}
}
}
return data ;
}
2021-09-28 09:09:52 +02:00
export function register _save _discard _widget _handlers (
2022-01-25 11:36:19 +01:00
$container ,
2021-09-28 09:09:52 +02:00
patch _url ,
for _realm _default _settings ,
) {
2022-01-25 11:36:19 +01:00
$container . on ( "change input" , "input, select, textarea" , ( e ) => {
2018-03-14 23:50:17 +01:00
e . preventDefault ( ) ;
e . stopPropagation ( ) ;
2019-08-22 01:48:38 +02:00
// This event handler detects whether after these input
// changes, any fields have different values from the current
// official values stored in the database and page_params. If
// they do, we transition to the "unsaved" state showing the
// save/discard widget; otherwise, we hide that widget (the
// "discarded" state).
2019-08-05 21:11:30 +02:00
if ( $ ( e . target ) . hasClass ( "no-input-change-detection" ) ) {
// This is to prevent input changes detection in elements
// within a subsection whose changes should not affect the
// visibility of the discard button
return false ;
}
2021-12-02 15:56:34 +01:00
if ( $ ( e . target ) . hasClass ( "setting_email_notifications_batching_period_seconds" ) ) {
const show _elem = $ ( e . target ) . val ( ) === "custom_period" ;
change _element _block _display _property (
"realm_email_notification_batching_period_edit_minutes" ,
show _elem ,
) ;
}
2022-11-03 13:18:42 +01:00
const $subsection = $ ( e . target ) . closest ( ".settings-subsection-parent" ) ;
2022-01-25 11:36:19 +01:00
save _discard _widget _status _handler ( $subsection , for _realm _default _settings ) ;
2020-09-24 07:50:36 +02:00
return undefined ;
2018-03-14 23:50:17 +01:00
} ) ;
2022-01-25 11:36:19 +01:00
$container . on ( "click" , ".subsection-header .subsection-changes-discard button" , ( e ) => {
2021-06-03 18:15:17 +02:00
e . preventDefault ( ) ;
e . stopPropagation ( ) ;
2022-11-03 13:18:42 +01:00
const $subsection = $ ( e . target ) . closest ( ".settings-subsection-parent" ) ;
2022-10-31 18:49:07 +01:00
for ( const elem of get _subsection _property _elements ( $subsection ) ) {
2021-09-28 09:09:52 +02:00
discard _property _element _changes ( elem , for _realm _default _settings ) ;
2021-06-03 18:15:17 +02:00
}
2022-01-25 11:36:19 +01:00
const $save _btn _controls = $ ( e . target ) . closest ( ".save-button-controls" ) ;
change _save _button _state ( $save _btn _controls , "discarded" ) ;
2021-06-03 18:15:17 +02:00
} ) ;
2018-03-14 23:52:36 +01:00
2018-03-21 00:50:00 +01:00
function get _complete _data _for _subsection ( subsection ) {
2019-11-02 00:06:25 +01:00
let data = { } ;
2020-02-21 21:45:34 +01:00
2021-05-09 23:36:58 +02:00
switch ( subsection ) {
case "notifications" :
2022-05-03 08:06:40 +02:00
data . default _language = $ (
"#org-notifications .language_selection_widget .language_selection_button span" ,
) . attr ( "data-language-code" ) ;
2021-05-09 23:36:58 +02:00
break ;
2022-12-07 12:16:37 +01:00
case "join_settings" : {
2021-05-09 23:36:58 +02:00
const org _join _restrictions = $ ( "#id_realm_org_join_restrictions" ) . val ( ) ;
switch ( org _join _restrictions ) {
case "only_selected_domain" :
data . emails _restricted _to _domains = true ;
data . disallow _disposable _email _addresses = false ;
break ;
case "no_disposable_email" :
data . emails _restricted _to _domains = false ;
data . disallow _disposable _email _addresses = true ;
break ;
case "no_restriction" :
data . disallow _disposable _email _addresses = false ;
data . emails _restricted _to _domains = false ;
break ;
}
break ;
2018-04-30 18:26:59 +02:00
}
2021-05-09 23:36:58 +02:00
case "auth_settings" :
data = { } ;
2022-07-07 10:14:13 +02:00
data . authentication _methods = JSON . stringify ( get _auth _method _list _data ( ) ) ;
2021-05-09 23:36:58 +02:00
break ;
2018-03-14 23:45:42 +01:00
}
2019-03-25 11:52:55 +01:00
return data ;
2018-03-21 00:50:00 +01:00
}
2022-01-25 11:36:19 +01:00
$container . on ( "click" , ".subsection-header .subsection-changes-save button" , ( e ) => {
2018-03-21 00:50:00 +01:00
e . preventDefault ( ) ;
e . stopPropagation ( ) ;
2022-01-25 11:36:19 +01:00
const $save _button = $ ( e . currentTarget ) ;
2022-11-03 13:18:42 +01:00
const $subsection _elem = $save _button . closest ( ".settings-subsection-parent" ) ;
2021-09-28 09:09:52 +02:00
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.
2022-12-07 12:16:37 +01:00
const [ , subsection _id ] = /^org-(.*)$/ . exec ( $subsection _elem . attr ( "id" ) ) ;
2023-05-11 21:49:10 +02:00
const subsection = subsection _id . replaceAll ( "-" , "_" ) ;
2021-09-28 09:09:52 +02:00
extra _data = get _complete _data _for _subsection ( subsection ) ;
}
2018-03-21 00:50:00 +01:00
2020-02-09 04:15:38 +01:00
const data = {
2022-11-09 17:54:47 +01:00
... populate _data _for _request ( $subsection _elem , for _realm _default _settings ) ,
2021-09-28 09:09:52 +02:00
... extra _data ,
2020-02-09 04:15:38 +01:00
} ;
2022-01-25 11:36:19 +01:00
save _organization _settings ( data , $save _button , patch _url ) ;
2017-05-25 00:50:07 +02:00
} ) ;
2021-09-29 13:03:35 +02:00
}
export function build _page ( ) {
meta . loaded = true ;
loading . make _indicator ( $ ( "#admin_page_auth_methods_loading_indicator" ) ) ;
// Initialize all the dropdown list widgets.
init _dropdown _widgets ( ) ;
// Populate realm domains
2021-07-20 14:51:48 +02:00
populate _realm _domains _label ( page _params . realm _domains ) ;
2021-09-29 13:03:35 +02:00
// Populate authentication methods table
populate _auth _methods ( page _params . realm _authentication _methods ) ;
for ( const property _name of simple _dropdown _properties ) {
set _property _dropdown _value ( property _name ) ;
}
2022-12-12 18:21:08 +01:00
set _realm _waiting _period _setting ( ) ;
2021-09-29 13:03:35 +02:00
set _video _chat _provider _dropdown ( ) ;
set _giphy _rating _dropdown ( ) ;
set _msg _edit _limit _dropdown ( ) ;
2022-12-22 19:14:23 +01:00
set _msg _move _limit _setting ( "realm_move_messages_within_stream_limit_seconds" ) ;
2023-01-30 12:15:36 +01:00
set _msg _move _limit _setting ( "realm_move_messages_between_streams_limit_seconds" ) ;
2021-09-29 13:03:35 +02:00
set _msg _delete _limit _dropdown ( ) ;
2022-08-18 16:14:05 +02:00
set _delete _own _message _policy _dropdown ( page _params . realm _delete _own _message _policy ) ;
2021-09-29 13:03:35 +02:00
set _message _retention _setting _dropdown ( ) ;
set _org _join _restrictions _dropdown ( ) ;
2023-01-02 20:50:23 +01:00
set _message _content _in _email _notifications _visibility ( ) ;
2021-09-29 13:03:35 +02:00
set _digest _emails _weekday _visibility ( ) ;
2021-11-19 10:29:39 +01:00
set _create _web _public _stream _dropdown _visibility ( ) ;
2021-09-29 13:03:35 +02:00
2021-09-28 09:09:52 +02:00
register _save _discard _widget _handlers ( $ ( ".admin-realm-form" ) , "/json/realm" , false ) ;
2017-08-18 01:23:55 +02:00
2022-11-03 13:18:42 +01:00
$ ( ".settings-subsection-parent" ) . on ( "keydown" , "input" , ( e ) => {
2018-03-22 14:16:53 +01:00
e . stopPropagation ( ) ;
2022-09-28 08:27:24 +02:00
if ( keydown _util . is _enter _event ( e ) ) {
2018-03-22 14:16:53 +01:00
e . preventDefault ( ) ;
2020-07-15 00:34:28 +02:00
$ ( e . target )
2022-11-03 13:18:42 +01:00
. closest ( ".settings-subsection-parent" )
2021-06-03 18:15:17 +02:00
. find ( ".subsection-changes-save button" )
2020-07-20 21:24:26 +02:00
. trigger ( "click" ) ;
2018-03-22 14:16:53 +01:00
}
} ) ;
2022-09-02 13:58:03 +02:00
$ ( "#id_realm_message_content_edit_limit_seconds" ) . on ( "change" , ( ) => {
update _custom _value _input ( "realm_message_content_edit_limit_seconds" ) ;
2018-04-02 11:18:40 +02:00
} ) ;
2023-01-30 12:15:36 +01:00
$ ( "#id_realm_move_messages_between_streams_limit_seconds" ) . on ( "change" , ( ) => {
update _custom _value _input ( "realm_move_messages_between_streams_limit_seconds" ) ;
} ) ;
2022-12-22 19:14:23 +01:00
$ ( "#id_realm_move_messages_within_stream_limit_seconds" ) . on ( "change" , ( ) => {
update _custom _value _input ( "realm_move_messages_within_stream_limit_seconds" ) ;
} ) ;
2022-09-02 13:58:03 +02:00
$ ( "#id_realm_message_content_delete_limit_seconds" ) . on ( "change" , ( ) => {
update _custom _value _input ( "realm_message_content_delete_limit_seconds" ) ;
2017-11-26 09:12:10 +01:00
} ) ;
2023-09-19 18:10:23 +02:00
$ ( "#id_realm_video_chat_provider" ) . on ( "change" , ( ) => {
set _jitsi _server _url _dropdown ( ) ;
} ) ;
$ ( "#id_realm_jitsi_server_url" ) . on ( "change" , ( e ) => {
const dropdown _val = e . target . value ;
update _jitsi _server _url _custom _input ( dropdown _val ) ;
} ) ;
2022-11-04 11:11:33 +01:00
$ ( "#id_realm_message_retention_days" ) . on ( "change" , ( e ) => {
2020-05-07 13:19:54 +02:00
const message _retention _setting _dropdown _value = e . target . value ;
2020-07-15 00:34:28 +02:00
change _element _block _display _property (
2022-11-04 11:11:33 +01:00
"id_realm_message_retention_custom_input" ,
2022-11-04 11:11:33 +01:00
message _retention _setting _dropdown _value === "custom_period" ,
2020-07-15 00:34:28 +02:00
) ;
2020-05-07 13:19:54 +02:00
} ) ;
2022-12-13 12:32:01 +01:00
$ ( "#id_realm_waiting_period_threshold" ) . on ( "change" , function ( ) {
2019-11-02 00:06:25 +01:00
const waiting _period _threshold = this . value ;
2020-07-15 00:34:28 +02:00
change _element _block _display _property (
2022-12-12 18:21:08 +01:00
"id_realm_waiting_period_threshold_custom_input" ,
2022-12-09 15:42:11 +01:00
waiting _period _threshold === "custom_period" ,
2020-07-15 00:34:28 +02:00
) ;
2018-01-05 15:34:10 +01:00
} ) ;
2022-02-20 12:06:19 +01:00
$ ( "#id_realm_digest_emails_enabled" ) . on ( "change" , ( e ) => {
const digest _emails _enabled = $ ( e . target ) . is ( ":checked" ) ;
change _element _block _display _property (
"id_realm_digest_weekday" ,
digest _emails _enabled === true ,
) ;
} ) ;
2020-07-20 21:26:58 +02:00
$ ( "#id_realm_org_join_restrictions" ) . on ( "change" , ( e ) => {
2019-11-02 00:06:25 +01:00
const org _join _restrictions = e . target . value ;
2022-01-25 11:36:19 +01:00
const $node = $ ( "#allowed_domains_label" ) . parent ( ) ;
2020-07-15 01:29:15 +02:00
if ( org _join _restrictions === "only_selected_domain" ) {
2022-01-25 11:36:19 +01:00
$node . show ( ) ;
2020-02-08 06:23:59 +01:00
if ( page _params . realm _domains . length === 0 ) {
2021-07-20 14:51:48 +02:00
settings _realm _domains . show _realm _domains _modal ( ) ;
2018-04-05 00:54:31 +02:00
}
} else {
2022-01-25 11:36:19 +01:00
$node . hide ( ) ;
2018-04-05 00:54:31 +02:00
}
} ) ;
2022-04-12 09:56:58 +02:00
$ ( "#id_realm_allow_message_editing" ) . on ( "change" , ( e ) => {
const is _checked = $ ( e . target ) . prop ( "checked" ) ;
update _message _edit _sub _settings ( is _checked ) ;
} ) ;
2022-12-22 19:14:23 +01:00
$ ( "#org-moving-msgs" ) . on ( "change" , ".move-message-policy-setting" , ( e ) => {
const $policy _dropdown _elem = $ ( e . target ) ;
const property _name = extract _property _name ( $policy _dropdown _elem ) ;
const disable _time _limit _setting = message _move _limit _setting _enabled ( property _name ) ;
2023-01-30 12:15:36 +01:00
let time _limit _setting _name ;
if ( property _name === "realm_edit_topic_policy" ) {
time _limit _setting _name = "realm_move_messages_within_stream_limit_seconds" ;
} else {
time _limit _setting _name = "realm_move_messages_between_streams_limit_seconds" ;
}
2022-12-22 19:14:23 +01:00
enable _or _disable _related _message _move _time _limit _setting (
time _limit _setting _name ,
disable _time _limit _setting ,
) ;
} ) ;
2022-04-25 12:58:35 +02:00
$ ( "#id_realm_delete_own_message_policy" ) . on ( "change" , ( e ) => {
const setting _value = Number . parseInt ( $ ( e . target ) . val ( ) , 10 ) ;
2022-08-18 16:22:46 +02:00
set _delete _own _message _policy _dropdown ( setting _value ) ;
2022-04-25 12:58:35 +02:00
} ) ;
2020-07-20 21:26:58 +02:00
$ ( "#id_realm_org_join_restrictions" ) . on ( "click" , ( e ) => {
2018-04-05 00:54:31 +02:00
// This prevents the disappearance of modal when there are
// no allowed domains otherwise it gets closed due to
// the click event handler attached to `#settings_overlay_container`
e . stopPropagation ( ) ;
} ) ;
2021-07-20 14:51:48 +02:00
$ ( "#show_realm_domains_modal" ) . on ( "click" , ( e ) => {
2017-04-08 18:13:39 +02:00
e . stopPropagation ( ) ;
2021-07-20 14:51:48 +02:00
settings _realm _domains . show _realm _domains _modal ( ) ;
2017-04-08 18:13:39 +02:00
} ) ;
2022-01-25 11:36:19 +01:00
function realm _icon _logo _upload _complete ( $spinner , $upload _text , $delete _button ) {
$spinner . css ( { visibility : "hidden" } ) ;
$upload _text . show ( ) ;
$delete _button . show ( ) ;
2020-05-27 14:16:04 +02:00
}
2022-01-25 11:36:19 +01:00
function realm _icon _logo _upload _start ( $spinner , $upload _text , $delete _button ) {
$spinner . css ( { visibility : "visible" } ) ;
$upload _text . hide ( ) ;
$delete _button . hide ( ) ;
2020-05-27 14:16:04 +02:00
}
2022-01-25 11:36:19 +01:00
function upload _realm _logo _or _icon ( $file _input , night , icon ) {
2019-11-02 00:06:25 +01:00
const form _data = new FormData ( ) ;
2020-06-17 08:02:33 +02:00
let widget ;
2020-06-11 01:04:12 +02:00
let url ;
2018-08-16 01:26:55 +02:00
2020-07-15 01:29:15 +02:00
form _data . append ( "csrfmiddlewaretoken" , csrf _token ) ;
2022-01-25 11:36:19 +01:00
for ( const [ i , file ] of Array . prototype . entries . call ( $file _input [ 0 ] . files ) ) {
2020-07-15 01:29:15 +02:00
form _data . append ( "file-" + i , file ) ;
2020-02-08 01:53:49 +01:00
}
2020-06-11 01:04:12 +02:00
if ( icon ) {
2020-07-15 01:29:15 +02:00
url = "/json/realm/icon" ;
widget = "#realm-icon-upload-widget" ;
2019-01-27 08:25:10 +01:00
} else {
2020-06-11 01:04:12 +02:00
if ( night ) {
2020-07-15 01:29:15 +02:00
widget = "#realm-night-logo-upload-widget" ;
2020-06-11 01:04:12 +02:00
} else {
2020-07-15 01:29:15 +02:00
widget = "#realm-day-logo-upload-widget" ;
2020-06-11 01:04:12 +02:00
}
2020-07-15 01:29:15 +02:00
url = "/json/realm/logo" ;
form _data . append ( "night" , JSON . stringify ( night ) ) ;
2019-01-27 08:25:10 +01:00
}
2022-01-25 11:36:19 +01:00
const $spinner = $ ( ` ${ widget } .upload-spinner-background ` ) . expectOne ( ) ;
const $upload _text = $ ( ` ${ widget } .image-upload-text ` ) . expectOne ( ) ;
const $delete _button = $ ( ` ${ widget } .image-delete-button ` ) . expectOne ( ) ;
const $error _field = $ ( ` ${ widget } .image_file_input_error ` ) . expectOne ( ) ;
realm _icon _logo _upload _start ( $spinner , $upload _text , $delete _button ) ;
$error _field . hide ( ) ;
2018-08-16 01:26:55 +02:00
channel . post ( {
2020-07-20 22:18:43 +02:00
url ,
2018-08-16 01:26:55 +02:00
data : form _data ,
cache : false ,
processData : false ,
contentType : false ,
2020-07-20 22:18:43 +02:00
success ( ) {
2022-01-25 11:36:19 +01:00
realm _icon _logo _upload _complete ( $spinner , $upload _text , $delete _button ) ;
2018-08-16 01:26:55 +02:00
} ,
2020-07-20 22:18:43 +02:00
error ( xhr ) {
2022-01-25 11:36:19 +01:00
realm _icon _logo _upload _complete ( $spinner , $upload _text , $delete _button ) ;
ui _report . error ( "" , xhr , $error _field ) ;
2018-08-16 01:26:55 +02:00
} ,
} ) ;
}
2019-02-27 15:45:26 +01:00
2020-06-11 01:04:12 +02:00
realm _icon . build _realm _icon _widget ( upload _realm _logo _or _icon , null , true ) ;
2020-05-08 13:30:34 +02:00
if ( page _params . zulip _plan _is _not _limited ) {
2020-06-11 01:04:12 +02:00
realm _logo . build _realm _logo _widget ( upload _realm _logo _or _icon , false ) ;
realm _logo . build _realm _logo _widget ( upload _realm _logo _or _icon , true ) ;
2019-06-12 14:22:37 +02:00
}
2019-03-11 16:48:59 +01:00
2022-10-11 14:20:27 +02:00
$ ( "#organization-profile .deactivate_realm_button" ) . on ( "click" , deactivate _organization ) ;
2021-02-28 01:20:46 +01:00
}