custom_profile_fields_ui: Convert module to TypeScript.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
Anders Kaseorg 2024-06-06 16:50:16 -07:00 committed by Tim Abbott
parent e6bfaed782
commit c9e822f7ad
2 changed files with 55 additions and 39 deletions

View File

@ -90,7 +90,7 @@ EXEMPT_FILES = make_set(
"web/src/csrf.ts", "web/src/csrf.ts",
"web/src/css_variables.d.ts", "web/src/css_variables.d.ts",
"web/src/css_variables.js", "web/src/css_variables.js",
"web/src/custom_profile_fields_ui.js", "web/src/custom_profile_fields_ui.ts",
"web/src/dark_theme.ts", "web/src/dark_theme.ts",
"web/src/debug.ts", "web/src/debug.ts",
"web/src/demo_organizations_ui.js", "web/src/demo_organizations_ui.js",

View File

@ -1,4 +1,6 @@
import flatpickr from "flatpickr";
import $ from "jquery"; import $ from "jquery";
import {z} from "zod";
import render_settings_custom_user_profile_field from "../templates/settings/custom_user_profile_field.hbs"; import render_settings_custom_user_profile_field from "../templates/settings/custom_user_profile_field.hbs";
@ -7,11 +9,15 @@ import * as bootstrap_typeahead from "./bootstrap_typeahead";
import {$t} from "./i18n"; import {$t} from "./i18n";
import * as people from "./people"; import * as people from "./people";
import * as pill_typeahead from "./pill_typeahead"; import * as pill_typeahead from "./pill_typeahead";
import * as settings_components from "./settings_components";
import {realm} from "./state_data"; import {realm} from "./state_data";
import * as typeahead_helper from "./typeahead_helper"; import * as typeahead_helper from "./typeahead_helper";
import type {UserPillWidget} from "./user_pill";
import * as user_pill from "./user_pill"; import * as user_pill from "./user_pill";
export function append_custom_profile_fields(element_id, user_id) { const user_value_schema = z.array(z.number());
export function append_custom_profile_fields(element_id: string, user_id: number): void {
const person = people.get_by_user_id(user_id); const person = people.get_by_user_id(user_id);
if (person.is_bot) { if (person.is_bot) {
return; return;
@ -39,15 +45,15 @@ export function append_custom_profile_fields(element_id, user_id) {
field_value = {value: "", rendered_value: ""}; field_value = {value: "", rendered_value: ""};
} }
if (is_select_field) { if (is_select_field) {
const field_choice_dict = JSON.parse(field.field_data); const field_choice_dict = settings_components.select_field_data_schema.parse(
for (const choice in field_choice_dict) { JSON.parse(field.field_data),
if (choice) { );
field_choices[field_choice_dict[choice].order] = { for (const [value, {order, text}] of Object.entries(field_choice_dict)) {
value: choice, field_choices[Number(order)] = {
text: field_choice_dict[choice].text, value,
selected: choice === field_value.value, text,
}; selected: value === field_value.value,
} };
} }
} }
@ -70,13 +76,25 @@ export function append_custom_profile_fields(element_id, user_id) {
} }
export function initialize_custom_user_type_fields( export function initialize_custom_user_type_fields(
element_id, element_id: string,
user_id, user_id: number,
is_editable, is_editable: boolean,
pill_update_handler, pill_update_handler?: (
) { field: {
type: number;
field_data: string;
hint: string;
id: number;
name: string;
order: number;
required: boolean;
display_in_profile_summary?: boolean | undefined;
},
pills: UserPillWidget,
) => void,
): Map<number, UserPillWidget> {
const field_types = realm.custom_profile_field_types; const field_types = realm.custom_profile_field_types;
const user_pills = new Map(); const user_pills = new Map<number, UserPillWidget>();
const person = people.get_by_user_id(user_id); const person = people.get_by_user_id(user_id);
if (person.is_bot) { if (person.is_bot) {
@ -84,37 +102,35 @@ export function initialize_custom_user_type_fields(
} }
for (const field of realm.custom_profile_fields) { for (const field of realm.custom_profile_fields) {
let field_value_raw = people.get_custom_profile_data(user_id, field.id); const field_value_raw = people.get_custom_profile_data(user_id, field.id)?.value;
if (field_value_raw) {
field_value_raw = field_value_raw.value;
}
// If field is not editable and field value is null, we don't expect // If field is not editable and field value is null, we don't expect
// pill container for that field and proceed further // pill container for that field and proceed further
if (field.type === field_types.USER.id && (field_value_raw || is_editable)) { if (field.type === field_types.USER.id && (field_value_raw !== undefined || is_editable)) {
const $pill_container = $(element_id) const $pill_container = $(element_id)
.find(`.custom_user_field[data-field-id="${CSS.escape(field.id)}"] .pill-container`) .find(
`.custom_user_field[data-field-id="${CSS.escape(`${field.id}`)}"] .pill-container`,
)
.expectOne(); .expectOne();
const pill_config = { const pill_config = {
exclude_inaccessible_users: is_editable, exclude_inaccessible_users: is_editable,
}; };
const pills = user_pill.create_pills($pill_container, pill_config); const pills = user_pill.create_pills($pill_container, pill_config);
if (field_value_raw) { if (field_value_raw !== undefined) {
const field_value = JSON.parse(field_value_raw); const field_value = user_value_schema.parse(JSON.parse(field_value_raw));
if (field_value) { for (const pill_user_id of field_value) {
for (const pill_user_id of field_value) { const user = people.get_user_by_id_assert_valid(pill_user_id);
const user = people.get_user_by_id_assert_valid(pill_user_id); user_pill.append_user(user, pills);
user_pill.append_user(user, pills);
}
} }
} }
if (is_editable) { if (is_editable) {
const $input = $pill_container.children(".input"); const $input = $pill_container.children(".input");
if (pill_update_handler) { if (pill_update_handler) {
const update_func = () => pill_update_handler(field, pills); const update_func = (): void => {
pill_update_handler(field, pills);
};
const opts = { const opts = {
update_func, update_func,
exclude_bots: true, exclude_bots: true,
@ -134,8 +150,8 @@ export function initialize_custom_user_type_fields(
return user_pills; return user_pills;
} }
export function initialize_custom_date_type_fields(element_id) { export function initialize_custom_date_type_fields(element_id: string): void {
$(element_id).find(".custom_user_field .datepicker").flatpickr({ flatpickr($(element_id).find(".custom_user_field .datepicker")[0]!, {
altInput: true, altInput: true,
altFormat: "F j, Y", altFormat: "F j, Y",
allowInput: true, allowInput: true,
@ -143,9 +159,9 @@ export function initialize_custom_date_type_fields(element_id) {
}); });
$(element_id) $(element_id)
.find(".custom_user_field .datepicker") .find<HTMLInputElement>(".custom_user_field input.datepicker")
.on("mouseenter", function () { .on("mouseenter", function () {
if ($(this).val().length <= 0) { if ($(this).val()!.length <= 0) {
$(this).parent().find(".remove_date").hide(); $(this).parent().find(".remove_date").hide();
} else { } else {
$(this).parent().find(".remove_date").show(); $(this).parent().find(".remove_date").show();
@ -161,15 +177,15 @@ export function initialize_custom_date_type_fields(element_id) {
}); });
} }
export function initialize_custom_pronouns_type_fields(element_id) { export function initialize_custom_pronouns_type_fields(element_id: string): void {
const commonly_used_pronouns = [ const commonly_used_pronouns = [
$t({defaultMessage: "he/him"}), $t({defaultMessage: "he/him"}),
$t({defaultMessage: "she/her"}), $t({defaultMessage: "she/her"}),
$t({defaultMessage: "they/them"}), $t({defaultMessage: "they/them"}),
]; ];
const bootstrap_typeahead_input = { const bootstrap_typeahead_input = {
$element: $(element_id).find(".pronouns_type_field"), $element: $(element_id).find<HTMLInputElement>("input.pronouns_type_field"),
type: "input", type: "input" as const,
}; };
new Typeahead(bootstrap_typeahead_input, { new Typeahead(bootstrap_typeahead_input, {
items: 3, items: 3,