mirror of https://github.com/zulip/zulip.git
settings_account: Convert module to typescript.
This commit is contained in:
parent
8eb0ca3a7c
commit
35424adcc3
|
@ -210,7 +210,7 @@ EXEMPT_FILES = make_set(
|
||||||
"web/src/sentry.ts",
|
"web/src/sentry.ts",
|
||||||
"web/src/server_events.js",
|
"web/src/server_events.js",
|
||||||
"web/src/settings.js",
|
"web/src/settings.js",
|
||||||
"web/src/settings_account.js",
|
"web/src/settings_account.ts",
|
||||||
"web/src/settings_bots.ts",
|
"web/src/settings_bots.ts",
|
||||||
"web/src/settings_components.ts",
|
"web/src/settings_components.ts",
|
||||||
"web/src/settings_emoji.ts",
|
"web/src/settings_emoji.ts",
|
||||||
|
|
|
@ -77,12 +77,7 @@ export function append_custom_profile_fields(element_id: string, user_id: number
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function initialize_custom_user_type_fields(
|
export type PillUpdateField = {
|
||||||
element_id: string,
|
|
||||||
user_id: number,
|
|
||||||
is_target_element_editable: boolean,
|
|
||||||
pill_update_handler?: (
|
|
||||||
field: {
|
|
||||||
type: number;
|
type: number;
|
||||||
field_data: string;
|
field_data: string;
|
||||||
hint: string;
|
hint: string;
|
||||||
|
@ -91,9 +86,13 @@ export function initialize_custom_user_type_fields(
|
||||||
order: number;
|
order: number;
|
||||||
required: boolean;
|
required: boolean;
|
||||||
display_in_profile_summary?: boolean | undefined;
|
display_in_profile_summary?: boolean | undefined;
|
||||||
},
|
};
|
||||||
pills: UserPillWidget,
|
|
||||||
) => void,
|
export function initialize_custom_user_type_fields(
|
||||||
|
element_id: string,
|
||||||
|
user_id: number,
|
||||||
|
is_target_element_editable: boolean,
|
||||||
|
pill_update_handler?: (field: PillUpdateField, pills: UserPillWidget) => void,
|
||||||
): Map<number, UserPillWidget> {
|
): Map<number, UserPillWidget> {
|
||||||
const field_types = realm.custom_profile_field_types;
|
const field_types = realm.custom_profile_field_types;
|
||||||
const user_pills = new Map<number, UserPillWidget>();
|
const user_pills = new Map<number, UserPillWidget>();
|
||||||
|
|
|
@ -746,6 +746,9 @@ export function dispatch_normal_event(event) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO/typescript: Move privacy_setting_name_schema and PrivacySettingName
|
||||||
|
// here from `settings_account` when this file is converted to typescript,
|
||||||
|
// and use them instead of `privacy_settings`.
|
||||||
const privacy_settings = [
|
const privacy_settings = [
|
||||||
"send_stream_typing_notifications",
|
"send_stream_typing_notifications",
|
||||||
"send_private_typing_notifications",
|
"send_private_typing_notifications",
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
import $ from "jquery";
|
import $ from "jquery";
|
||||||
|
import assert from "minimalistic-assert";
|
||||||
|
import {z} from "zod";
|
||||||
|
|
||||||
import render_change_email_modal from "../templates/change_email_modal.hbs";
|
import render_change_email_modal from "../templates/change_email_modal.hbs";
|
||||||
import render_demo_organization_add_email_modal from "../templates/demo_organization_add_email_modal.hbs";
|
import render_demo_organization_add_email_modal from "../templates/demo_organization_add_email_modal.hbs";
|
||||||
|
@ -7,11 +9,11 @@ import render_settings_api_key_modal from "../templates/settings/api_key_modal.h
|
||||||
import render_settings_dev_env_email_access from "../templates/settings/dev_env_email_access.hbs";
|
import render_settings_dev_env_email_access from "../templates/settings/dev_env_email_access.hbs";
|
||||||
|
|
||||||
import * as avatar from "./avatar";
|
import * as avatar from "./avatar";
|
||||||
import * as blueslip from "./blueslip";
|
|
||||||
import * as channel from "./channel";
|
import * as channel from "./channel";
|
||||||
import * as common from "./common";
|
import * as common from "./common";
|
||||||
import {csrf_token} from "./csrf";
|
import {csrf_token} from "./csrf";
|
||||||
import * as custom_profile_fields_ui from "./custom_profile_fields_ui";
|
import * as custom_profile_fields_ui from "./custom_profile_fields_ui";
|
||||||
|
import type {PillUpdateField} from "./custom_profile_fields_ui";
|
||||||
import * as dialog_widget from "./dialog_widget";
|
import * as dialog_widget from "./dialog_widget";
|
||||||
import {$t_html} from "./i18n";
|
import {$t_html} from "./i18n";
|
||||||
import * as keydown_util from "./keydown_util";
|
import * as keydown_util from "./keydown_util";
|
||||||
|
@ -29,13 +31,17 @@ import * as ui_report from "./ui_report";
|
||||||
import * as ui_util from "./ui_util";
|
import * as ui_util from "./ui_util";
|
||||||
import * as user_deactivation_ui from "./user_deactivation_ui";
|
import * as user_deactivation_ui from "./user_deactivation_ui";
|
||||||
import * as user_pill from "./user_pill";
|
import * as user_pill from "./user_pill";
|
||||||
|
import type {UserPillWidget} from "./user_pill";
|
||||||
import * as user_profile from "./user_profile";
|
import * as user_profile from "./user_profile";
|
||||||
import {user_settings} from "./user_settings";
|
import {user_settings} from "./user_settings";
|
||||||
|
import * as util from "./util";
|
||||||
|
|
||||||
let password_quality; // Loaded asynchronously
|
let password_quality:
|
||||||
|
| ((password: string, $bar: JQuery | undefined, $password_field: JQuery) => boolean)
|
||||||
|
| undefined; // Loaded asynchronously
|
||||||
let user_avatar_widget_created = false;
|
let user_avatar_widget_created = false;
|
||||||
|
|
||||||
export function update_email(new_email) {
|
export function update_email(new_email: string): void {
|
||||||
const $email_input = $("#change_email_button");
|
const $email_input = $("#change_email_button");
|
||||||
|
|
||||||
if ($email_input) {
|
if ($email_input) {
|
||||||
|
@ -43,7 +49,7 @@ export function update_email(new_email) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function update_full_name(new_full_name) {
|
export function update_full_name(new_full_name: string): void {
|
||||||
// Arguably, this should work more like how the `update_email`
|
// Arguably, this should work more like how the `update_email`
|
||||||
// flow works, where we update the name in the modal on open,
|
// flow works, where we update the name in the modal on open,
|
||||||
// rather than updating it here, but this works.
|
// rather than updating it here, but this works.
|
||||||
|
@ -53,7 +59,7 @@ export function update_full_name(new_full_name) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function update_name_change_display() {
|
export function update_name_change_display(): void {
|
||||||
if ($("#user_details_section").length === 0) {
|
if ($("#user_details_section").length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -67,7 +73,7 @@ export function update_name_change_display() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function update_email_change_display() {
|
export function update_email_change_display(): void {
|
||||||
if ($("#user_details_section").length === 0) {
|
if ($("#user_details_section").length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -81,24 +87,27 @@ export function update_email_change_display() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function display_avatar_upload_complete() {
|
function display_avatar_upload_complete(): void {
|
||||||
$("#user-avatar-upload-widget .upload-spinner-background").css({visibility: "hidden"});
|
$("#user-avatar-upload-widget .upload-spinner-background").css({visibility: "hidden"});
|
||||||
$("#user-avatar-upload-widget .image-upload-text").show();
|
$("#user-avatar-upload-widget .image-upload-text").show();
|
||||||
$("#user-avatar-upload-widget .image-delete-button").show();
|
$("#user-avatar-upload-widget .image-delete-button").show();
|
||||||
}
|
}
|
||||||
|
|
||||||
function display_avatar_upload_started() {
|
function display_avatar_upload_started(): void {
|
||||||
$("#user-avatar-source").hide();
|
$("#user-avatar-source").hide();
|
||||||
$("#user-avatar-upload-widget .upload-spinner-background").css({visibility: "visible"});
|
$("#user-avatar-upload-widget .upload-spinner-background").css({visibility: "visible"});
|
||||||
$("#user-avatar-upload-widget .image-upload-text").hide();
|
$("#user-avatar-upload-widget .image-upload-text").hide();
|
||||||
$("#user-avatar-upload-widget .image-delete-button").hide();
|
$("#user-avatar-upload-widget .image-delete-button").hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
function upload_avatar($file_input) {
|
function upload_avatar($file_input: JQuery<HTMLInputElement>): void {
|
||||||
const form_data = new FormData();
|
const form_data = new FormData();
|
||||||
|
|
||||||
|
assert(csrf_token !== undefined);
|
||||||
form_data.append("csrfmiddlewaretoken", csrf_token);
|
form_data.append("csrfmiddlewaretoken", csrf_token);
|
||||||
for (const [i, file] of Array.prototype.entries.call($file_input[0].files)) {
|
const files = util.the($file_input).files;
|
||||||
|
assert(files !== null);
|
||||||
|
for (const [i, file] of [...files].entries()) {
|
||||||
form_data.append("file-" + i, file);
|
form_data.append("file-" + i, file);
|
||||||
}
|
}
|
||||||
display_avatar_upload_started();
|
display_avatar_upload_started();
|
||||||
|
@ -119,16 +128,17 @@ function upload_avatar($file_input) {
|
||||||
if (current_user.avatar_source === "G") {
|
if (current_user.avatar_source === "G") {
|
||||||
$("#user-avatar-source").show();
|
$("#user-avatar-source").show();
|
||||||
}
|
}
|
||||||
if (xhr.responseJSON?.msg) {
|
const parsed = z.object({msg: z.string()}).safeParse(xhr.responseJSON);
|
||||||
|
if (parsed.success) {
|
||||||
const $error = $("#user-avatar-upload-widget .image_file_input_error");
|
const $error = $("#user-avatar-upload-widget .image_file_input_error");
|
||||||
$error.text(xhr.responseJSON.msg);
|
$error.text(parsed.data.msg);
|
||||||
$error.show();
|
$error.show();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function update_avatar_change_display() {
|
export function update_avatar_change_display(): void {
|
||||||
if ($("#user-avatar-upload-widget").length === 0) {
|
if ($("#user-avatar-upload-widget").length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -137,7 +147,7 @@ export function update_avatar_change_display() {
|
||||||
$("#user-avatar-upload-widget .image_upload_button").addClass("hide");
|
$("#user-avatar-upload-widget .image_upload_button").addClass("hide");
|
||||||
$("#user-avatar-upload-widget .image-disabled").removeClass("hide");
|
$("#user-avatar-upload-widget .image-disabled").removeClass("hide");
|
||||||
} else {
|
} else {
|
||||||
if (user_avatar_widget_created === false) {
|
if (!user_avatar_widget_created) {
|
||||||
avatar.build_user_avatar_widget(upload_avatar);
|
avatar.build_user_avatar_widget(upload_avatar);
|
||||||
user_avatar_widget_created = true;
|
user_avatar_widget_created = true;
|
||||||
}
|
}
|
||||||
|
@ -146,7 +156,7 @@ export function update_avatar_change_display() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function update_account_settings_display() {
|
export function update_account_settings_display(): void {
|
||||||
if ($("#user_details_section").length === 0) {
|
if ($("#user_details_section").length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -156,7 +166,7 @@ export function update_account_settings_display() {
|
||||||
update_avatar_change_display();
|
update_avatar_change_display();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function maybe_update_deactivate_account_button() {
|
export function maybe_update_deactivate_account_button(): void {
|
||||||
if (!current_user.is_owner) {
|
if (!current_user.is_owner) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -173,7 +183,7 @@ export function maybe_update_deactivate_account_button() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function update_send_read_receipts_tooltip() {
|
export function update_send_read_receipts_tooltip(): void {
|
||||||
if (realm.realm_enable_read_receipts) {
|
if (realm.realm_enable_read_receipts) {
|
||||||
$("#send_read_receipts_label .settings-info-icon").hide();
|
$("#send_read_receipts_label .settings-info-icon").hide();
|
||||||
} else {
|
} else {
|
||||||
|
@ -181,11 +191,14 @@ export function update_send_read_receipts_tooltip() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function settings_change_error(message_html, xhr) {
|
function settings_change_error(message_html: string, xhr?: JQuery.jqXHR): void {
|
||||||
ui_report.error(message_html, xhr, $("#account-settings-status").expectOne());
|
ui_report.error(message_html, xhr, $("#account-settings-status").expectOne());
|
||||||
}
|
}
|
||||||
|
|
||||||
function update_custom_profile_field(field, method) {
|
function update_custom_profile_field(
|
||||||
|
field: CustomProfileFieldData,
|
||||||
|
method: channel.AjaxRequestHandler,
|
||||||
|
): void {
|
||||||
let data;
|
let data;
|
||||||
if (method === channel.del) {
|
if (method === channel.del) {
|
||||||
data = JSON.stringify([field.id]);
|
data = JSON.stringify([field.id]);
|
||||||
|
@ -199,17 +212,21 @@ function update_custom_profile_field(field, method) {
|
||||||
settings_ui.do_settings_change(method, "/json/users/me/profile_data", {data}, $spinner_element);
|
settings_ui.do_settings_change(method, "/json/users/me/profile_data", {data}, $spinner_element);
|
||||||
}
|
}
|
||||||
|
|
||||||
function update_user_custom_profile_fields(fields, method) {
|
type CustomProfileFieldData = {
|
||||||
if (method === undefined) {
|
id: number;
|
||||||
blueslip.error("Undefined method in update_user_custom_profile_fields");
|
value?: number[] | string;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
function update_user_custom_profile_fields(
|
||||||
|
fields: CustomProfileFieldData[],
|
||||||
|
method: channel.AjaxRequestHandler,
|
||||||
|
): void {
|
||||||
for (const field of fields) {
|
for (const field of fields) {
|
||||||
update_custom_profile_field(field, method);
|
update_custom_profile_field(field, method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function update_user_type_field(field, pills) {
|
function update_user_type_field(field: PillUpdateField, pills: UserPillWidget): void {
|
||||||
const user_ids = user_pill.get_user_ids(pills);
|
const user_ids = user_pill.get_user_ids(pills);
|
||||||
if (user_ids.length < 1) {
|
if (user_ids.length < 1) {
|
||||||
update_user_custom_profile_fields([{id: field.id}], channel.del);
|
update_user_custom_profile_fields([{id: field.id}], channel.del);
|
||||||
|
@ -218,7 +235,7 @@ function update_user_type_field(field, pills) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function add_custom_profile_fields_to_settings() {
|
export function add_custom_profile_fields_to_settings(): void {
|
||||||
if (!overlays.settings_open()) {
|
if (!overlays.settings_open()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -226,7 +243,9 @@ export function add_custom_profile_fields_to_settings() {
|
||||||
const element_id = "#profile-settings .custom-profile-fields-form";
|
const element_id = "#profile-settings .custom-profile-fields-form";
|
||||||
$(element_id).empty();
|
$(element_id).empty();
|
||||||
|
|
||||||
const pill_update_handler = (field, pills) => update_user_type_field(field, pills);
|
const pill_update_handler = (field: PillUpdateField, pills: UserPillWidget): void => {
|
||||||
|
update_user_type_field(field, pills);
|
||||||
|
};
|
||||||
|
|
||||||
custom_profile_fields_ui.append_custom_profile_fields(element_id, people.my_current_user_id());
|
custom_profile_fields_ui.append_custom_profile_fields(element_id, people.my_current_user_id());
|
||||||
custom_profile_fields_ui.initialize_custom_user_type_fields(
|
custom_profile_fields_ui.initialize_custom_user_type_fields(
|
||||||
|
@ -239,14 +258,25 @@ export function add_custom_profile_fields_to_settings() {
|
||||||
custom_profile_fields_ui.initialize_custom_pronouns_type_fields(element_id);
|
custom_profile_fields_ui.initialize_custom_pronouns_type_fields(element_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hide_confirm_email_banner() {
|
export function hide_confirm_email_banner(): void {
|
||||||
if (!overlays.settings_open()) {
|
if (!overlays.settings_open()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$("#account-settings-status").hide();
|
$("#account-settings-status").hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function update_privacy_settings_box(property) {
|
// TODO/typescript: Move these to server_events_dispatch when it's converted to typescript.
|
||||||
|
export const privacy_setting_name_schema = z.enum([
|
||||||
|
"send_stream_typing_notifications",
|
||||||
|
"send_private_typing_notifications",
|
||||||
|
"send_read_receipts",
|
||||||
|
"presence_enabled",
|
||||||
|
"email_address_visibility",
|
||||||
|
"allow_private_data_export",
|
||||||
|
]);
|
||||||
|
export type PrivacySettingName = z.infer<typeof privacy_setting_name_schema>;
|
||||||
|
|
||||||
|
export function update_privacy_settings_box(property: PrivacySettingName): void {
|
||||||
if (!overlays.settings_open()) {
|
if (!overlays.settings_open()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -256,19 +286,24 @@ export function update_privacy_settings_box(property) {
|
||||||
settings_components.set_input_element_value($input_elem, user_settings[property]);
|
settings_components.set_input_element_value($input_elem, user_settings[property]);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function set_up(load_password_quality) {
|
export function set_up(
|
||||||
|
load_password_quality: () => Promise<
|
||||||
|
(password: string, $bar: JQuery | undefined, $password_field: JQuery) => boolean
|
||||||
|
>,
|
||||||
|
): void {
|
||||||
// Add custom profile fields elements to user account settings.
|
// Add custom profile fields elements to user account settings.
|
||||||
add_custom_profile_fields_to_settings();
|
add_custom_profile_fields_to_settings();
|
||||||
$("#account-settings-status").hide();
|
$("#account-settings-status").hide();
|
||||||
|
|
||||||
const setup_api_key_modal = () => {
|
const setup_api_key_modal = (): void => {
|
||||||
function request_api_key(data) {
|
function request_api_key(data: {password?: string}): void {
|
||||||
channel.post({
|
channel.post({
|
||||||
url: "/json/fetch_api_key",
|
url: "/json/fetch_api_key",
|
||||||
data,
|
data,
|
||||||
success(data) {
|
success(data) {
|
||||||
$("#get_api_key_password").val("");
|
$("#get_api_key_password").val("");
|
||||||
$("#api_key_value").text(data.api_key);
|
const api_key = z.object({api_key: z.string()}).parse(data).api_key;
|
||||||
|
$("#api_key_value").text(api_key);
|
||||||
// The display property on the error bar is set to important
|
// The display property on the error bar is set to important
|
||||||
// so instead of making display: none !important we just
|
// so instead of making display: none !important we just
|
||||||
// remove it.
|
// remove it.
|
||||||
|
@ -298,14 +333,15 @@ export function set_up(load_password_quality) {
|
||||||
{tippy_tooltips: true},
|
{tippy_tooltips: true},
|
||||||
);
|
);
|
||||||
|
|
||||||
function do_get_api_key() {
|
function do_get_api_key(): void {
|
||||||
$("#api_key_status").hide();
|
$("#api_key_status").hide();
|
||||||
const data = {};
|
const data = {
|
||||||
data.password = $("#get_api_key_password").val();
|
password: $<HTMLInputElement>("input#get_api_key_password").val()!,
|
||||||
|
};
|
||||||
request_api_key(data);
|
request_api_key(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (realm.realm_password_auth_enabled === false) {
|
if (!realm.realm_password_auth_enabled) {
|
||||||
// Skip the password prompt step, since the user doesn't have one.
|
// Skip the password prompt step, since the user doesn't have one.
|
||||||
request_api_key({});
|
request_api_key({});
|
||||||
} else {
|
} else {
|
||||||
|
@ -334,11 +370,13 @@ export function set_up(load_password_quality) {
|
||||||
url: "/api/v1/users/me/api_key/regenerate",
|
url: "/api/v1/users/me/api_key/regenerate",
|
||||||
headers: {Authorization: authorization_header},
|
headers: {Authorization: authorization_header},
|
||||||
success(data) {
|
success(data) {
|
||||||
$("#api_key_value").text(data.api_key);
|
const api_key = z.object({api_key: z.string()}).parse(data).api_key;
|
||||||
|
$("#api_key_value").text(api_key);
|
||||||
},
|
},
|
||||||
error(xhr) {
|
error(xhr) {
|
||||||
if (xhr.responseJSON?.msg) {
|
const parsed = z.object({msg: z.string()}).safeParse(xhr.responseJSON);
|
||||||
$("#user_api_key_error").text(xhr.responseJSON.msg).show();
|
if (parsed.success) {
|
||||||
|
$("#user_api_key_error").text(parsed.data.msg).show();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -378,7 +416,7 @@ export function set_up(load_password_quality) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
});
|
});
|
||||||
|
|
||||||
function clear_password_change() {
|
function clear_password_change(): void {
|
||||||
// Clear the password boxes so that passwords don't linger in the DOM
|
// Clear the password boxes so that passwords don't linger in the DOM
|
||||||
// for an XSS attacker to find.
|
// for an XSS attacker to find.
|
||||||
common.reset_password_toggle_icons(
|
common.reset_password_toggle_icons(
|
||||||
|
@ -393,7 +431,7 @@ export function set_up(load_password_quality) {
|
||||||
password_quality?.("", $("#pw_strength .bar"), $("#new_password"));
|
password_quality?.("", $("#pw_strength .bar"), $("#new_password"));
|
||||||
}
|
}
|
||||||
|
|
||||||
function change_password_post_render() {
|
function change_password_post_render(): void {
|
||||||
$("#change_password_modal")
|
$("#change_password_modal")
|
||||||
.find("[data-micromodal-close]")
|
.find("[data-micromodal-close]")
|
||||||
.on("click", () => {
|
.on("click", () => {
|
||||||
|
@ -412,11 +450,11 @@ export function set_up(load_password_quality) {
|
||||||
clear_password_change();
|
clear_password_change();
|
||||||
}
|
}
|
||||||
|
|
||||||
$("#change_password").on("click", async (e) => {
|
$("#change_password").on("click", (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
function validate_input() {
|
function validate_input(): boolean {
|
||||||
const old_password = $("#old_password").val();
|
const old_password = $("#old_password").val();
|
||||||
const new_password = $("#new_password").val();
|
const new_password = $("#new_password").val();
|
||||||
|
|
||||||
|
@ -458,26 +496,29 @@ export function set_up(load_password_quality) {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (realm.realm_password_auth_enabled !== false) {
|
if (realm.realm_password_auth_enabled) {
|
||||||
// zxcvbn.js is pretty big, and is only needed on password
|
// zxcvbn.js is pretty big, and is only needed on password
|
||||||
// change, so load it asynchronously.
|
// change, so load it asynchronously.
|
||||||
|
void (async () => {
|
||||||
password_quality = await load_password_quality();
|
password_quality = await load_password_quality();
|
||||||
$("#pw_strength .bar").removeClass("hide");
|
$("#pw_strength .bar").removeClass("hide");
|
||||||
|
|
||||||
$("#new_password").on("input", () => {
|
$("#new_password").on("input", () => {
|
||||||
const $field = $("#new_password");
|
const $field = $<HTMLInputElement>("input#new_password");
|
||||||
password_quality($field.val(), $("#pw_strength .bar"), $field);
|
assert(password_quality !== undefined);
|
||||||
|
password_quality($field.val()!, $("#pw_strength .bar"), $field);
|
||||||
});
|
});
|
||||||
|
})();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function do_change_password() {
|
function do_change_password(): void {
|
||||||
const $change_password_error = $("#change_password_modal").find("#dialog_error");
|
const $change_password_error = $("#change_password_modal").find("#dialog_error");
|
||||||
$change_password_error.hide();
|
$change_password_error.hide();
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
old_password: $("#old_password").val(),
|
old_password: $("#old_password").val(),
|
||||||
new_password: $("#new_password").val(),
|
new_password: $<HTMLInputElement>("input#new_password").val()!,
|
||||||
};
|
};
|
||||||
|
|
||||||
const $new_pw_field = $("#new_password");
|
const $new_pw_field = $("#new_password");
|
||||||
|
@ -521,9 +562,9 @@ export function set_up(load_password_quality) {
|
||||||
$("#full_name").on("change", (e) => {
|
$("#full_name").on("change", (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
const data = {};
|
const data = {
|
||||||
|
full_name: $("#full_name").val(),
|
||||||
data.full_name = $("#full_name").val();
|
};
|
||||||
|
|
||||||
settings_ui.do_settings_change(
|
settings_ui.do_settings_change(
|
||||||
channel.patch,
|
channel.patch,
|
||||||
|
@ -533,10 +574,11 @@ export function set_up(load_password_quality) {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
function do_change_email() {
|
function do_change_email(): void {
|
||||||
const $change_email_error = $("#change_email_modal").find("#dialog_error");
|
const $change_email_error = $("#change_email_modal").find("#dialog_error");
|
||||||
const data = {};
|
const data = {
|
||||||
data.email = $("#change_email_form").find("input[name='email']").val();
|
email: $("#change_email_form").find<HTMLInputElement>("input[name='email']").val(),
|
||||||
|
};
|
||||||
|
|
||||||
const opts = {
|
const opts = {
|
||||||
success_continuation() {
|
success_continuation() {
|
||||||
|
@ -582,20 +624,21 @@ export function set_up(load_password_quality) {
|
||||||
form_id: "change_email_form",
|
form_id: "change_email_form",
|
||||||
on_click: do_change_email,
|
on_click: do_change_email,
|
||||||
on_shown() {
|
on_shown() {
|
||||||
ui_util.place_caret_at_end($("#change_email_form input")[0]);
|
ui_util.place_caret_at_end(util.the($("#change_email_form input")));
|
||||||
},
|
},
|
||||||
update_submit_disabled_state_on_change: true,
|
update_submit_disabled_state_on_change: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function do_demo_organization_add_email(e) {
|
function do_demo_organization_add_email(e: JQuery.ClickEvent): void {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
const $change_email_error = $("#demo_organization_add_email_modal").find("#dialog_error");
|
const $change_email_error = $("#demo_organization_add_email_modal").find("#dialog_error");
|
||||||
const data = {};
|
const data = {
|
||||||
data.email = $("#demo_organization_add_email").val();
|
email: $<HTMLInputElement>("input#demo_organization_add_email").val(),
|
||||||
data.full_name = $("#demo_organization_update_full_name").val();
|
full_name: $("#demo_organization_update_full_name").val(),
|
||||||
|
};
|
||||||
|
|
||||||
const opts = {
|
const opts = {
|
||||||
success_continuation() {
|
success_continuation() {
|
||||||
|
@ -632,10 +675,12 @@ export function set_up(load_password_quality) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
function demo_organization_add_email_post_render() {
|
function demo_organization_add_email_post_render(): void {
|
||||||
// Disable submit button if either input is an empty string.
|
// Disable submit button if either input is an empty string.
|
||||||
const $add_email_element = $("#demo_organization_add_email");
|
const $add_email_element = $<HTMLInputElement>("input#demo_organization_add_email");
|
||||||
const $add_name_element = $("#demo_organization_update_full_name");
|
const $add_name_element = $<HTMLInputElement>(
|
||||||
|
"input#demo_organization_update_full_name",
|
||||||
|
);
|
||||||
|
|
||||||
const $demo_organization_submit_button = $(
|
const $demo_organization_submit_button = $(
|
||||||
"#demo_organization_add_email_modal .dialog_submit_button",
|
"#demo_organization_add_email_modal .dialog_submit_button",
|
||||||
|
@ -645,7 +690,8 @@ export function set_up(load_password_quality) {
|
||||||
$("#demo_organization_add_email_form input").on("input", () => {
|
$("#demo_organization_add_email_form input").on("input", () => {
|
||||||
$demo_organization_submit_button.prop(
|
$demo_organization_submit_button.prop(
|
||||||
"disabled",
|
"disabled",
|
||||||
$add_email_element.val().trim() === "" || $add_name_element.val().trim() === "",
|
$add_email_element.val()!.trim() === "" ||
|
||||||
|
$add_name_element.val()!.trim() === "",
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -667,26 +713,33 @@ export function set_up(load_password_quality) {
|
||||||
form_id: "demo_organization_add_email_form",
|
form_id: "demo_organization_add_email_form",
|
||||||
on_click: do_demo_organization_add_email,
|
on_click: do_demo_organization_add_email,
|
||||||
on_shown() {
|
on_shown() {
|
||||||
ui_util.place_caret_at_end($("#demo_organization_add_email_form input")[0]);
|
ui_util.place_caret_at_end(
|
||||||
|
util.the($("#demo_organization_add_email_form input")),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
post_render: demo_organization_add_email_post_render,
|
post_render: demo_organization_add_email_post_render,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#profile-settings").on("click", ".custom_user_field .remove_date", (e) => {
|
$("#profile-settings").on(
|
||||||
|
"click",
|
||||||
|
".custom_user_field .remove_date",
|
||||||
|
function (this: HTMLElement, e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
const $field = $(this).closest(".custom_user_field").expectOne();
|
const $field = $(this).closest(".custom_user_field").expectOne();
|
||||||
const field_id = Number.parseInt($field.attr("data-field-id"), 10);
|
const field_id = Number.parseInt($field.attr("data-field-id")!, 10);
|
||||||
update_user_custom_profile_fields([{id: field_id}], channel.del);
|
update_user_custom_profile_fields([{id: field_id}], channel.del);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
$("#profile-settings").on("change", ".custom_user_field_value", function (e) {
|
$("#profile-settings").on("change", ".custom_user_field_value", function (this: HTMLElement) {
|
||||||
const fields = [];
|
const fields: CustomProfileFieldData[] = [];
|
||||||
const value = $(this).val();
|
const value = $(this).val()!;
|
||||||
|
assert(typeof value === "string");
|
||||||
const field_id = Number.parseInt(
|
const field_id = Number.parseInt(
|
||||||
$(this).closest(".custom_user_field").attr("data-field-id"),
|
$(this).closest(".custom_user_field").attr("data-field-id")!,
|
||||||
10,
|
10,
|
||||||
);
|
);
|
||||||
if (value) {
|
if (value) {
|
||||||
|
@ -708,7 +761,7 @@ export function set_up(load_password_quality) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
function handle_confirm() {
|
function handle_confirm(): void {
|
||||||
channel.del({
|
channel.del({
|
||||||
url: "/json/users/me",
|
url: "/json/users/me",
|
||||||
success() {
|
success() {
|
||||||
|
@ -732,9 +785,15 @@ export function set_up(load_password_quality) {
|
||||||
)}</a>`,
|
)}</a>`,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
let rendered_error_msg;
|
let rendered_error_msg = "";
|
||||||
if (xhr.responseJSON?.code === "CANNOT_DEACTIVATE_LAST_USER") {
|
const parsed = z
|
||||||
if (xhr.responseJSON.is_last_owner) {
|
.object({
|
||||||
|
code: z.literal("CANNOT_DEACTIVATE_LAST_USER"),
|
||||||
|
is_last_owner: z.boolean(),
|
||||||
|
})
|
||||||
|
.safeParse(xhr.responseJSON);
|
||||||
|
if (parsed.success) {
|
||||||
|
if (parsed.data.is_last_owner) {
|
||||||
rendered_error_msg = error_last_owner;
|
rendered_error_msg = error_last_owner;
|
||||||
} else {
|
} else {
|
||||||
rendered_error_msg = error_last_user;
|
rendered_error_msg = error_last_user;
|
||||||
|
@ -776,7 +835,7 @@ export function set_up(load_password_quality) {
|
||||||
|
|
||||||
$("#user_timezone").val(user_settings.timezone);
|
$("#user_timezone").val(user_settings.timezone);
|
||||||
|
|
||||||
$("#user_timezone").on("change", function (e) {
|
$<HTMLSelectElement>("select#user_timezone").on("change", function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
|
@ -790,13 +849,13 @@ export function set_up(load_password_quality) {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#privacy_settings_box").on("change", "input", (e) => {
|
$("#privacy_settings_box").on("change", "input", function (this: HTMLInputElement, e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
const $input_elem = $(this);
|
const $input_elem = $(this);
|
||||||
const setting_name = $input_elem.attr("name");
|
const setting_name = $input_elem.attr("name")!;
|
||||||
const checked = $input_elem.prop("checked");
|
const checked = util.the($input_elem).checked;
|
||||||
|
|
||||||
const data = {[setting_name]: checked};
|
const data = {[setting_name]: checked};
|
||||||
settings_ui.do_settings_change(
|
settings_ui.do_settings_change(
|
||||||
|
@ -809,7 +868,7 @@ export function set_up(load_password_quality) {
|
||||||
|
|
||||||
$("#user_email_address_visibility").val(user_settings.email_address_visibility);
|
$("#user_email_address_visibility").val(user_settings.email_address_visibility);
|
||||||
|
|
||||||
$("#user_email_address_visibility").on("change", function (e) {
|
$<HTMLSelectElement>("select#user_email_address_visibility").on("change", function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
|
@ -105,7 +105,12 @@ export function encode_zuliprc_as_url(zuliprc: string): string {
|
||||||
return "data:application/octet-stream;charset=utf-8," + encodeURIComponent(zuliprc);
|
return "data:application/octet-stream;charset=utf-8," + encodeURIComponent(zuliprc);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function generate_zuliprc_content(bot: bot_data.Bot): string {
|
export function generate_zuliprc_content(bot: {
|
||||||
|
bot_type?: number;
|
||||||
|
user_id: number;
|
||||||
|
email: string;
|
||||||
|
api_key: string;
|
||||||
|
}): string {
|
||||||
let token;
|
let token;
|
||||||
// For outgoing webhooks, include the token in the zuliprc.
|
// For outgoing webhooks, include the token in the zuliprc.
|
||||||
// It's needed for authenticating to the Botserver.
|
// It's needed for authenticating to the Botserver.
|
||||||
|
|
|
@ -920,7 +920,7 @@ function get_human_profile_data(fields_user_pills: Map<number, user_pill.UserPil
|
||||||
to see how the form is built.
|
to see how the form is built.
|
||||||
|
|
||||||
TODO: Ideally, this logic would be cleaned up or deduplicated with
|
TODO: Ideally, this logic would be cleaned up or deduplicated with
|
||||||
the settings_account.js logic.
|
the settings_account.ts logic.
|
||||||
*/
|
*/
|
||||||
const new_profile_data = [];
|
const new_profile_data = [];
|
||||||
$("#edit-user-form .custom_user_field_value").each(function () {
|
$("#edit-user-form .custom_user_field_value").each(function () {
|
||||||
|
|
Loading…
Reference in New Issue