diff --git a/web/src/invite.ts b/web/src/invite.ts index 689584ace4..1b5d966c0f 100644 --- a/web/src/invite.ts +++ b/web/src/invite.ts @@ -267,10 +267,8 @@ function valid_to(time_valid: number): string { return $t({defaultMessage: "Expires on {date} at {time}"}, {date, time}); } -function set_expires_on_text(): void { - const $expires_in = $("select:not([multiple])#expires_in"); - if ($expires_in.val() === "custom") { - $("#expires_on").hide(); +function set_custom_expires_on_text(): void { + if (util.validate_custom_time_input(custom_expiration_time_input)) { $("#custom_expires_on").text( valid_to( util.get_custom_time_in_minutes( @@ -279,6 +277,16 @@ function set_expires_on_text(): void { ), ), ); + } else { + $("#custom_expires_on").text($t({defaultMessage: "Invalid custom time"})); + } +} + +function set_expires_on_text(): void { + const $expires_in = $("select:not([multiple])#expires_in"); + if ($expires_in.val() === "custom") { + $("#expires_on").hide(); + set_custom_expires_on_text(); } else { $("#expires_on").show(); $("#expires_on").text(valid_to(Number.parseFloat($expires_in.val()!))); @@ -406,12 +414,14 @@ function open_invite_user_modal(e: JQuery.ClickEvent): void .find(".selected") .attr("data-tab-key"); } + const valid_custom_time = util.validate_custom_time_input(custom_expiration_time_input); const $button = $("#invite-user-modal .dialog_submit_button"); $button.prop( "disabled", - selected_tab === "invite-email-tab" && + (selected_tab === "invite-email-tab" && pills.items().length === 0 && - email_pill.get_current_email(pills) === null, + email_pill.get_current_email(pills) === null) || + ($expires_in.val() === "custom" && !valid_custom_time), ); if (selected_tab === "invite-email-tab") { $button.text($t({defaultMessage: "Invite"})); @@ -431,6 +441,7 @@ function open_invite_user_modal(e: JQuery.ClickEvent): void $expires_in.on("change", () => { set_custom_time_inputs_visibility(); set_expires_on_text(); + toggle_invite_submit_button(); }); $("#custom-expiration-time-input").on("keydown", (e) => { @@ -441,20 +452,14 @@ function open_invite_user_modal(e: JQuery.ClickEvent): void }); $(".custom-expiration-time").on("change", () => { - custom_expiration_time_input = Number.parseFloat( + custom_expiration_time_input = util.check_time_input( $("input#custom-expiration-time-input").val()!, ); custom_expiration_time_unit = $( "select:not([multiple])#custom-expiration-time-unit", ).val()!; - $("#custom_expires_on").text( - valid_to( - util.get_custom_time_in_minutes( - custom_expiration_time_unit, - custom_expiration_time_input, - ), - ), - ); + set_custom_expires_on_text(); + toggle_invite_submit_button(); }); $("#invite_check_all_button").on("click", () => { diff --git a/web/src/util.ts b/web/src/util.ts index 32e3598054..c1ee1c7f6f 100644 --- a/web/src/util.ts +++ b/web/src/util.ts @@ -467,6 +467,13 @@ export function check_time_input(input_value: string, keep_number_as_float = fal return Number.parseInt(input_value, 10); } +export function validate_custom_time_input(time_input: number): boolean { + if (Number.isNaN(time_input) || time_input < 0) { + return false; + } + return true; +} + // Helper for shorthand for Typescript to get an item from a list with // exactly one item. export function the(items: T[] | JQuery): T { diff --git a/web/tests/util.test.js b/web/tests/util.test.js index f93d8777e5..255a356ac7 100644 --- a/web/tests/util.test.js +++ b/web/tests/util.test.js @@ -408,20 +408,24 @@ run_test("check_and_validate_custom_time_input", () => { const input_is_nan = "24abc"; let checked_input = util.check_time_input(input_is_nan); assert.equal(checked_input, Number.NaN); + assert.equal(util.validate_custom_time_input(checked_input), false); const input_is_negative = "-24"; checked_input = util.check_time_input(input_is_negative); assert.equal(checked_input, -24); + assert.equal(util.validate_custom_time_input(input_is_negative), false); const input_is_float = "24.5"; checked_input = util.check_time_input(input_is_float); assert.equal(checked_input, 24); checked_input = util.check_time_input(input_is_float, true); assert.equal(checked_input, 24.5); + assert.equal(util.validate_custom_time_input(input_is_float), true); const input_is_integer = "10"; checked_input = util.check_time_input(input_is_integer); assert.equal(checked_input, 10); + assert.equal(util.validate_custom_time_input(input_is_integer), true); }); run_test("the", () => {