invite: Convert module to TypeScript.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
Anders Kaseorg 2023-09-22 01:32:06 -07:00 committed by Tim Abbott
parent eefd7feafa
commit d6884399b2
5 changed files with 82 additions and 49 deletions

View File

@ -101,7 +101,7 @@ EXEMPT_FILES = make_set(
"web/src/inbox_ui.js",
"web/src/inbox_util.js",
"web/src/info_overlay.js",
"web/src/invite.js",
"web/src/invite.ts",
"web/src/lightbox.js",
"web/src/list_util.ts",
"web/src/list_widget.ts",

2
web/src/hbs.d.ts vendored
View File

@ -1,4 +1,4 @@
declare module "*.hbs" {
const render: (context: unknown) => string;
const render: (context?: unknown) => string;
export = render;
}

View File

@ -2,6 +2,7 @@ import autosize from "autosize";
import ClipboardJS from "clipboard";
import {add} from "date-fns";
import $ from "jquery";
import assert from "minimalistic-assert";
import copy_invite_link from "../templates/copy_invite_link.hbs";
import render_invitation_failed_error from "../templates/invitation_failed_error.hbs";
@ -26,7 +27,7 @@ import * as util from "./util";
let custom_expiration_time_input = 10;
let custom_expiration_time_unit = "days";
function reset_error_messages() {
function reset_error_messages(): void {
$("#dialog_error").hide().text("").removeClass(common.status_classes);
if (page_params.development_environment) {
@ -34,39 +35,52 @@ function reset_error_messages() {
}
}
function get_common_invitation_data() {
const invite_as = Number.parseInt($("#invite_as").val(), 10);
let expires_in = $("#expires_in").val();
function get_common_invitation_data(): {
csrfmiddlewaretoken: string;
invite_as: number;
stream_ids: string;
invite_expires_in_minutes: string;
invitee_emails?: string;
} {
const invite_as = Number.parseInt(
$<HTMLSelectElement & {type: "select-one"}>("select:not([multiple])#invite_as").val()!,
10,
);
const raw_expires_in = $<HTMLSelectElement & {type: "select-one"}>(
"select:not([multiple])#expires_in",
).val()!;
// See settings_config.expires_in_values for why we do this conversion.
if (expires_in === "null") {
expires_in = JSON.stringify(null);
} else if (expires_in === "custom") {
expires_in = Number.parseFloat(get_expiration_time_in_minutes());
let expires_in: number | null;
if (raw_expires_in === "null") {
expires_in = null;
} else if (raw_expires_in === "custom") {
expires_in = get_expiration_time_in_minutes();
} else {
expires_in = Number.parseFloat($("#expires_in").val());
expires_in = Number.parseFloat(raw_expires_in);
}
let stream_ids = [];
let stream_ids: number[] = [];
const default_stream_ids = stream_data.get_default_stream_ids();
if (default_stream_ids.length !== 0 && $("#invite_select_default_streams").prop("checked")) {
stream_ids = default_stream_ids;
} else {
$("#invite-stream-checkboxes input:checked").each(function () {
const stream_id = Number.parseInt($(this).val(), 10);
$<HTMLInputElement>("#invite-stream-checkboxes input:checked").each(function () {
const stream_id = Number.parseInt($(this).val()!, 10);
stream_ids.push(stream_id);
});
}
assert(csrf_token !== undefined);
const data = {
csrfmiddlewaretoken: csrf_token,
invite_as,
stream_ids: JSON.stringify(stream_ids),
invite_expires_in_minutes: expires_in,
invite_expires_in_minutes: JSON.stringify(expires_in),
};
return data;
}
function beforeSend() {
function beforeSend(): void {
reset_error_messages();
// TODO: You could alternatively parse the textarea here, and return errors to
// the user if they don't match certain constraints (i.e. not real email addresses,
@ -76,16 +90,18 @@ function beforeSend() {
const loading_text = $("#invite-user-modal .dialog_submit_button").data("loading-text");
$("#invite-user-modal .dialog_submit_button").text(loading_text);
$("#invite-user-modal .dialog_submit_button").prop("disabled", true);
return true;
}
function submit_invitation_form() {
function submit_invitation_form(): void {
const $expires_in = $<HTMLSelectElement & {type: "select-one"}>(
"select:not([multiple])#expires_in",
);
const $invite_status = $("#dialog_error");
const $invitee_emails = $("#invitee_emails");
const $invitee_emails = $<HTMLTextAreaElement>("textarea#invitee_emails");
const data = get_common_invitation_data();
data.invitee_emails = $("#invitee_emails").val();
data.invitee_emails = $invitee_emails.val()!;
channel.post({
void channel.post({
url: "/json/invites",
data,
beforeSend,
@ -101,14 +117,14 @@ function submit_invitation_form() {
$("#dev_env_msg").html(rendered_email_msg).addClass("alert-info").show();
}
if ($("#expires_in").val() === "custom") {
if ($expires_in.val() === "custom") {
// Hide the custom inputs if the custom input is set
// to one of the dropdown's standard options.
const time_in_minutes = get_expiration_time_in_minutes();
for (const option of Object.values(settings_config.expires_in_values)) {
if (option.value === time_in_minutes) {
$("#custom-invite-expiration-time").hide();
$("#expires_in").val(time_in_minutes);
$expires_in.val(time_in_minutes);
return;
}
}
@ -153,16 +169,16 @@ function submit_invitation_form() {
$("#invite-user-modal .dialog_submit_button").text($t({defaultMessage: "Invite"}));
$("#invite-user-modal .dialog_submit_button").prop("disabled", false);
$("#invite-user-modal .dialog_exit_button").prop("disabled", false);
$("#invitee_emails").trigger("focus");
$<HTMLTextAreaElement>("textarea#invitee_emails").trigger("focus");
scroll_util.get_scroll_element($("#invite-user-modal"))[0].scrollTop = 0;
},
});
}
function generate_multiuse_invite() {
function generate_multiuse_invite(): void {
const $invite_status = $("#dialog_error");
const data = get_common_invitation_data();
channel.post({
void channel.post({
url: "/json/invites/multiuse",
data,
beforeSend,
@ -185,14 +201,13 @@ function generate_multiuse_invite() {
});
}
export function get_invite_streams() {
export function get_invite_streams(): stream_data.InviteStreamData[] {
const streams = stream_data.get_invite_stream_data();
streams.sort((a, b) => util.strcmp(a.name, b.name));
return streams;
}
function valid_to(expires_in) {
const time_valid = Number.parseFloat(expires_in);
function valid_to(time_valid: number): string {
if (!time_valid) {
return $t({defaultMessage: "Never expires"});
}
@ -205,7 +220,7 @@ function valid_to(expires_in) {
return $t({defaultMessage: "Expires on {date} at {time}"}, {date, time});
}
function get_expiration_time_in_minutes() {
function get_expiration_time_in_minutes(): number {
switch (custom_expiration_time_unit) {
case "hours":
return custom_expiration_time_input * 60;
@ -218,27 +233,35 @@ function get_expiration_time_in_minutes() {
}
}
function set_expires_on_text() {
if ($("#expires_in").val() === "custom") {
function set_expires_on_text(): void {
const $expires_in = $<HTMLSelectElement & {type: "select-one"}>(
"select:not([multiple])#expires_in",
);
if ($expires_in.val() === "custom") {
$("#expires_on").hide();
$("#custom_expires_on").text(valid_to(get_expiration_time_in_minutes()));
} else {
$("#expires_on").show();
$("#expires_on").text(valid_to($("#expires_in").val()));
$("#expires_on").text(valid_to(Number.parseFloat($expires_in.val()!)));
}
}
function set_custom_time_inputs_visibility() {
if ($("#expires_in").val() === "custom") {
function set_custom_time_inputs_visibility(): void {
const $expires_in = $<HTMLSelectElement & {type: "select-one"}>(
"select:not([multiple])#expires_in",
);
if ($expires_in.val() === "custom") {
$("#custom-expiration-time-input").val(custom_expiration_time_input);
$("#custom-expiration-time-unit").val(custom_expiration_time_unit);
$<HTMLSelectElement & {type: "select-one"}>(
"select:not([multiple])#custom-expiration-time-unit",
).val(custom_expiration_time_unit);
$("#custom-invite-expiration-time").show();
} else {
$("#custom-invite-expiration-time").hide();
}
}
function set_streams_to_join_list_visibility() {
function set_streams_to_join_list_visibility(): void {
const default_streams_selected = $("#invite_select_default_streams").prop("checked");
if (default_streams_selected) {
$("#streams_to_add .invite-stream-controls").hide();
@ -249,7 +272,7 @@ function set_streams_to_join_list_visibility() {
}
}
function open_invite_user_modal(e) {
function open_invite_user_modal(e: JQuery.ClickEvent<Document, undefined>): void {
e.stopPropagation();
e.preventDefault();
@ -269,7 +292,12 @@ function open_invite_user_modal(e) {
user_has_email_set: !settings_data.user_email_not_configured(),
});
function invite_user_modal_post_render() {
function invite_user_modal_post_render(): void {
const $expires_in = $<HTMLSelectElement & {type: "select-one"}>(
"select:not([multiple])#expires_in",
);
const $invitee_emails = $<HTMLTextAreaElement>("textarea#invitee_emails");
$("#invite-user-modal .dialog_submit_button").prop("disabled", true);
$("#email_invite_radio").prop("checked", true);
@ -281,16 +309,16 @@ function open_invite_user_modal(e) {
const user_has_email_set = !settings_data.user_email_not_configured();
autosize($("#invitee_emails").trigger("focus"));
autosize($invitee_emails.trigger("focus"));
set_custom_time_inputs_visibility();
set_expires_on_text();
set_streams_to_join_list_visibility();
function toggle_invite_submit_button() {
function toggle_invite_submit_button(): void {
$("#invite-user-modal .dialog_submit_button").prop(
"disabled",
$("#invitee_emails").val().trim() === "" &&
$invitee_emails.val()!.trim() === "" &&
!$("#generate_multiuse_invite_radio").is(":checked"),
);
}
@ -323,12 +351,12 @@ function open_invite_user_modal(e) {
reset_error_messages();
});
$("#expires_in").on("change", () => {
$expires_in.on("change", () => {
set_custom_time_inputs_visibility();
set_expires_on_text();
});
$("#expires_on").text(valid_to($("#expires_in").val()));
$("#expires_on").text(valid_to(Number.parseFloat($expires_in.val()!)));
$("#custom-expiration-time-input").on("keydown", (e) => {
if (e.key === "Enter") {
@ -338,8 +366,12 @@ function open_invite_user_modal(e) {
});
$(".custom-expiration-time").on("change", () => {
custom_expiration_time_input = $("#custom-expiration-time-input").val();
custom_expiration_time_unit = $("#custom-expiration-time-unit").val();
custom_expiration_time_input = Number.parseFloat(
$<HTMLInputElement>("#custom-expiration-time-input").val()!,
);
custom_expiration_time_unit = $<HTMLSelectElement & {type: "select-one"}>(
"select:not([multiple])#custom-expiration-time-unit",
).val()!;
$("#custom_expires_on").text(valid_to(get_expiration_time_in_minutes()));
});
@ -371,7 +403,7 @@ function open_invite_user_modal(e) {
}
}
function invite_users() {
function invite_users(): void {
const is_generate_invite_link = $("#generate_multiuse_invite_radio").prop("checked");
if (is_generate_invite_link) {
generate_multiuse_invite();
@ -391,6 +423,6 @@ function open_invite_user_modal(e) {
});
}
export function initialize() {
export function initialize(): void {
$(document).on("click", ".invite-user-link", open_invite_user_modal);
}

View File

@ -15,6 +15,7 @@ export const page_params: {
login_page: string;
delivery_email: string;
is_admin: boolean;
is_billing_admin: boolean;
is_bot: boolean;
is_guest: boolean;
is_moderator: boolean;

View File

@ -33,7 +33,7 @@ type ApiGenericStreamSubscription =
| ApiStreamSubscription
| (Stream & {stream_weekly_traffic: number | null; subscribers: number[]});
type InviteStreamData = {
export type InviteStreamData = {
name: string;
stream_id: number;
invite_only: boolean;