org_settings: Add frontend support for realm_jitsi_server_url.

This commit adds a dropdown and custom input element to set the
`realm_jitsi_server_url` when the video call provider is Jitsi. This
allows organization administrators to add a custom Jitsi server as the
organization's video call provider.

Fixes #17914.

Co-authored-by: Gaurav Pandey <gauravguitarrocks@gmail.com>
This commit is contained in:
Hemant Umre
2023-09-19 21:40:23 +05:30
committed by Tim Abbott
parent be653dd5b4
commit f731602024
7 changed files with 180 additions and 11 deletions

View File

@@ -99,6 +99,7 @@ export function build_page() {
realm_name: page_params.realm_name,
realm_org_type: page_params.realm_org_type,
realm_available_video_chat_providers: page_params.realm_available_video_chat_providers,
server_jitsi_server_url: page_params.server_jitsi_server_url,
giphy_rating_options: page_params.giphy_rating_options,
giphy_api_key_empty: page_params.giphy_api_key === "",
realm_description: page_params.realm_description,

View File

@@ -59,6 +59,11 @@ let uppy;
export function get_compose_upload_object() {
return uppy;
}
function get_jitsi_server_url() {
return page_params.realm_jitsi_server_url ?? page_params.server_jitsi_server_url;
}
export function compute_show_video_chat_button() {
const available_providers = page_params.realm_available_video_chat_providers;
if (page_params.realm_video_chat_provider === available_providers.disabled.id) {
@@ -67,7 +72,7 @@ export function compute_show_video_chat_button() {
if (
page_params.realm_video_chat_provider === available_providers.jitsi_meet.id &&
!page_params.jitsi_server_url
!get_jitsi_server_url()
) {
return false;
}
@@ -90,7 +95,7 @@ export function compute_show_audio_chat_button() {
const available_providers = page_params.realm_available_video_chat_providers;
if (
(available_providers.jitsi_meet &&
page_params.jitsi_server_url &&
get_jitsi_server_url() &&
page_params.realm_video_chat_provider === available_providers.jitsi_meet.id) ||
(available_providers.zoom &&
page_params.realm_video_chat_provider === available_providers.zoom.id)
@@ -940,7 +945,7 @@ function generate_and_insert_audio_or_video_call_link($target_element, is_audio_
} else {
// TODO: Use `new URL` to generate the URLs here.
const video_call_id = util.random_int(100000000000000, 999999999999999);
const video_call_link = page_params.jitsi_server_url + "/" + video_call_id;
const video_call_link = get_jitsi_server_url() + "/" + video_call_id;
if (is_audio_call) {
insert_audio_call_url(
video_call_link + "#config.startWithVideoMuted=true",

View File

@@ -232,6 +232,7 @@ export function dispatch_normal_event(event) {
signup_notifications_stream_id: noop,
emails_restricted_to_domains: noop,
video_chat_provider: compose.update_audio_and_video_chat_button_display,
jitsi_server_url: compose.update_audio_and_video_chat_button_display,
giphy_rating: giphy.update_giphy_rating,
waiting_period_threshold: noop,
want_advertise_in_communities_directory: noop,

View File

@@ -266,9 +266,70 @@ function set_realm_waiting_period_setting() {
);
}
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);
}
function set_video_chat_provider_dropdown() {
const chat_provider_id = page_params.realm_video_chat_provider;
$("#id_realm_video_chat_provider").val(chat_provider_id);
set_jitsi_server_url_dropdown();
}
function set_giphy_rating_dropdown() {
@@ -712,6 +773,9 @@ export function discard_property_element_changes(elem, for_realm_default_setting
case "realm_video_chat_provider":
set_video_chat_provider_dropdown();
break;
case "realm_jitsi_server_url":
set_jitsi_server_url_dropdown();
break;
case "realm_message_retention_days":
case "message_retention_days":
set_message_retention_setting_dropdown(sub);
@@ -888,6 +952,8 @@ export function get_input_element_value(input_elem, input_type) {
}
case "time-limit":
return get_time_limit_setting_value($input_elem);
case "jitsi-server-url-setting":
return get_jitsi_server_url_setting_value($input_elem);
case "message-retention-setting":
return get_message_retention_setting_value($input_elem);
case "dropdown-list-widget":
@@ -1003,6 +1069,9 @@ export function check_property_changed(elem, for_realm_default_settings, sub) {
case "message_retention_days":
proposed_val = get_message_retention_setting_value($elem, false);
break;
case "realm_jitsi_server_url":
proposed_val = get_jitsi_server_url_setting_value($elem, false);
break;
case "realm_default_language":
proposed_val = $(
"#org-notifications .language_selection_widget .language_selection_button span",
@@ -1212,8 +1281,23 @@ function check_maximum_valid_value($custom_input_elem, property_name) {
return setting_value <= MAX_CUSTOM_TIME_LIMIT_SETTING_VALUE;
}
function enable_or_disable_save_button($subsection_elem) {
const time_limit_settings = [...$subsection_elem.find(".time-limit-setting")];
function is_valid_url(jitsi_url) {
const url_pattern = /^(https?:\/\/)/;
return url_pattern.test(jitsi_url);
}
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");
return $dropdown_elem.val() === "custom" && !is_valid_url($custom_input_elem.val());
}
function should_disable_save_button_for_time_limit_settings(time_limit_settings) {
let disable_save_btn = false;
for (const setting_elem of time_limit_settings) {
const $dropdown_elem = $(setting_elem).find("select");
@@ -1245,6 +1329,20 @@ function enable_or_disable_save_button($subsection_elem) {
break;
}
}
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();
}
$subsection_elem.find(".subsection-changes-save button").prop("disabled", disable_save_btn);
}
@@ -1453,6 +1551,15 @@ export function build_page() {
update_custom_value_input("realm_message_content_delete_limit_seconds");
});
$("#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);
});
$("#id_realm_message_retention_days").on("change", (e) => {
const message_retention_setting_dropdown_value = e.target.value;
change_element_block_display_property(

View File

@@ -1508,7 +1508,8 @@ $option_title_width: 180px;
}
}
.time-limit-custom-input {
.time-limit-custom-input,
.realm_jitsi_server_url_custom_input {
padding: 4px 6px;
color: hsl(0deg 0% 33%);
border: 1px solid hsl(0deg 0% 80%);
@@ -1525,6 +1526,16 @@ $option_title_width: 180px;
}
}
#realm_jitsi_server_url_setting {
display: flex;
flex-wrap: wrap;
gap: 15px;
.jitsi_server_url_custom_input_label {
margin-bottom: 3px;
}
}
#profile-settings,
#edit-user-form {
.custom_user_field {

View File

@@ -114,6 +114,32 @@
<option value='{{this.id}}'>{{this.name}}</option>
{{/each}}
</select>
<div class="dependent-settings-block" id="realm_jitsi_server_url_setting">
<div>
<label for="id_realm_jitsi_server_url" class="dropdown-title">
{{t "Jitsi server URL" }}
</label>
<select name="realm_jitsi_server_url" id="id_realm_jitsi_server_url" class="setting-widget prop-element settings_select bootstrap-focus-style" data-setting-widget-type="jitsi-server-url-setting">
{{#if server_jitsi_server_url}}
<option value="server_default">
{{#tr}}{server_jitsi_server_url} (default){{/tr}}
</option>
{{else}}
<option value="server_default">{{t 'Disabled' }}</option>
{{/if}}
<option value="custom">{{t 'Custom URL' }}</option>
</select>
</div>
<div>
<label for="id_realm_jitsi_server_url_custom_input" class="jitsi_server_url_custom_input_label">
{{t 'URL' }}
</label>
<input type="text" id="id_realm_jitsi_server_url_custom_input" autocomplete="off"
name="realm_jitsi_server_url_custom_input" class="realm_jitsi_server_url_custom_input settings_url_input"/>
</div>
</div>
</div>
<div class="input-group">
<label for="realm_giphy_rating" class="dropdown-title">

View File

@@ -119,15 +119,33 @@ test("videos", ({override}) => {
page_params.realm_video_chat_provider = realm_available_video_chat_providers.jitsi_meet.id;
page_params.jitsi_server_url = null;
page_params.realm_jitsi_server_url = null;
page_params.server_jitsi_server_url = null;
handler(ev);
assert.ok(!called);
page_params.jitsi_server_url = "https://meet.jit.si";
page_params.realm_jitsi_server_url = null;
page_params.server_jitsi_server_url = "https://server.example.com";
handler(ev);
// video link ids consist of 15 random digits
const video_link_regex =
/\[translated: Join video call\.]\(https:\/\/meet.jit.si\/\d{15}#config.startWithVideoMuted=false\)/;
let video_link_regex =
/\[translated: Join video call\.]\(https:\/\/server.example.com\/\d{15}#config.startWithVideoMuted=false\)/;
assert.ok(called);
assert.match(syntax_to_insert, video_link_regex);
page_params.realm_jitsi_server_url = "https://realm.example.com";
page_params.server_jitsi_server_url = null;
handler(ev);
video_link_regex =
/\[translated: Join video call\.]\(https:\/\/realm.example.com\/\d{15}#config.startWithVideoMuted=false\)/;
assert.ok(called);
assert.match(syntax_to_insert, video_link_regex);
page_params.realm_jitsi_server_url = "https://realm.example.com";
page_params.server_jitsi_server_url = "https://server.example.com";
handler(ev);
video_link_regex =
/\[translated: Join video call\.]\(https:\/\/realm.example.com\/\d{15}#config.startWithVideoMuted=false\)/;
assert.ok(called);
assert.match(syntax_to_insert, video_link_regex);
})();
@@ -252,7 +270,7 @@ test("test_video_chat_button_toggle enabled", ({override}) => {
override(upload, "feature_check", () => {});
page_params.realm_video_chat_provider = realm_available_video_chat_providers.jitsi_meet.id;
page_params.jitsi_server_url = "https://meet.jit.si";
page_params.realm_jitsi_server_url = "https://meet.jit.si";
compose.initialize();
assert.equal($("#below-compose-content .video_link").visible(), true);
});