user_invite: Convert invite modal to tabbed format.

This commit converts the radio buttons (for
selecting email/link) to tab
components in the user invite modal.

The selected tab is in focus by default and arrow keys
can be used to toggle the selected tab.

Appropriate tooltips are shown when a tab is disabled.

Fixes #29392.
This commit is contained in:
Kislay Verma 2024-04-12 17:10:37 +05:30 committed by Tim Abbott
parent b41a116d42
commit 505d66afeb
5 changed files with 61 additions and 67 deletions

View File

@ -11,6 +11,7 @@ import render_settings_dev_env_email_access from "../templates/settings/dev_env_
import * as channel from "./channel";
import * as common from "./common";
import * as components from "./components";
import * as compose_banner from "./compose_banner";
import {show_copied_confirmation} from "./copied_tooltip";
import {csrf_token} from "./csrf";
@ -348,16 +349,8 @@ function open_invite_user_modal(e: JQuery.ClickEvent<Document, undefined>): void
get_text_from_item: email_pill.get_email_from_item,
});
const $pill_input = $("#invitee_emails_container .pill-container .input");
$pill_input.trigger("focus");
$("#invite-user-modal .dialog_submit_button").prop("disabled", true);
$("#email_invite_radio").prop("checked", true);
if (!settings_data.user_can_create_multiuse_invite()) {
$("#generate_multiuse_invite_radio").prop("disabled", true);
$("#generate_multiuse_invite_radio_container").addClass("control-label-disabled");
$("#generate_multiuse_invite_radio_container").addClass("disabled_setting_tooltip");
}
const user_has_email_set = !settings_data.user_email_not_configured();
@ -375,12 +368,20 @@ function open_invite_user_modal(e: JQuery.ClickEvent<Document, undefined>): void
});
function toggle_invite_submit_button(): void {
$("#invite-user-modal .dialog_submit_button").prop(
const $button = $("#invite-user-modal .dialog_submit_button");
$button.prop(
"disabled",
pills.items().length === 0 &&
email_pill.get_current_email(pills) === null &&
!$("#generate_multiuse_invite_radio").is(":checked"),
$pill_input.is(":visible") &&
pills.items().length === 0 &&
email_pill.get_current_email(pills) === null,
);
if ($("#invitee_emails_container").is(":visible")) {
$button.text($t({defaultMessage: "Invite"}));
$button.data("loading-text", $t({defaultMessage: "Inviting..."}));
} else {
$button.text($t({defaultMessage: "Generate invite link"}));
$button.data("loading-text", $t({defaultMessage: "Generating link..."}));
}
}
pills.onPillCreate(toggle_invite_submit_button);
@ -391,30 +392,6 @@ function open_invite_user_modal(e: JQuery.ClickEvent<Document, undefined>): void
toggle_invite_submit_button();
});
$("#invite-user-modal").on("change", "#email_invite_radio", () => {
$("#invitee_emails_container").show();
$("#invite-user-modal .dialog_submit_button").text($t({defaultMessage: "Invite"}));
$("#invite-user-modal .dialog_submit_button").data(
"loading-text",
$t({defaultMessage: "Inviting..."}),
);
toggle_invite_submit_button();
reset_error_messages();
});
$("#invite-user-modal").on("change", "#generate_multiuse_invite_radio", () => {
$("#invitee_emails_container").hide();
$("#invite-user-modal .dialog_submit_button").text(
$t({defaultMessage: "Generate invite link"}),
);
$("#invite-user-modal .dialog_submit_button").data(
"loading-text",
$t({defaultMessage: "Generating link..."}),
);
$("#invite-user-modal .dialog_submit_button").prop("disabled", false);
reset_error_messages();
});
$expires_in.on("change", () => {
set_custom_time_inputs_visibility();
set_expires_on_text();
@ -456,16 +433,6 @@ function open_invite_user_modal(e: JQuery.ClickEvent<Document, undefined>): void
$("#invite-user-form :input").prop("disabled", !user_has_email_set);
}
if (!settings_data.user_can_invite_users_by_email()) {
$("#email_invite_radio").prop("disabled", true);
$("#email_invite_radio_container").addClass(
"control-label-disabled disabled_setting_tooltip",
);
$("#generate_multiuse_invite_radio").prop("checked", true);
$("#generate_multiuse_invite_radio").trigger("change");
}
const invite_tips_data = generate_invite_tips_data();
const context = {
@ -475,10 +442,47 @@ function open_invite_user_modal(e: JQuery.ClickEvent<Document, undefined>): void
};
$("#invite-user-form .setup-tips-container").html(render_invite_tips_banner(context));
const toggler = components.toggle({
html_class: "invite_users_option_tabs large allow-overflow",
selected: 0,
child_wants_focus: true,
values: [
{label: $t({defaultMessage: "Send invite email"}), key: "invite-email-tab"},
{label: $t({defaultMessage: "Create invite link"}), key: "invite-link-tab"},
],
callback(_name, key) {
switch (key) {
case "invite-email-tab":
$("#invitee_emails_container").show();
break;
case "invite-link-tab":
$("#invitee_emails_container").hide();
break;
}
toggle_invite_submit_button();
reset_error_messages();
},
});
const $container = $("#invite_users_option_tabs_container");
if (!settings_data.user_can_invite_users_by_email()) {
toggler.disable_tab("invite-email-tab");
toggler.goto("invite-link-tab");
}
if (!settings_data.user_can_create_multiuse_invite()) {
toggler.disable_tab("invite-link-tab");
}
const $elem = toggler.get();
$container.append($elem);
setTimeout(() => {
$(".invite_users_option_tabs .ind-tab.selected").trigger("focus");
}, 0);
}
function invite_users(): void {
const is_generate_invite_link = $("#generate_multiuse_invite_radio").prop("checked");
const is_generate_invite_link =
$(".invite_users_option_tabs").find(".selected").attr("data-tab-key") ===
"invite-link-tab";
if (is_generate_invite_link) {
generate_multiuse_invite();
} else {

View File

@ -400,10 +400,10 @@ export function initialize(): void {
});
delegate("body", {
target: "#generate_multiuse_invite_radio_container.disabled_setting_tooltip",
target: "[data-tab-key='invite-link-tab'].disabled",
content: $t({
defaultMessage:
"You do not have permissions to generate invite links in this organization.",
"You do not have permissions to create invite links in this organization.",
}),
appendTo: () => document.body,
onHidden(instance) {
@ -426,10 +426,10 @@ export function initialize(): void {
});
delegate("body", {
target: "#email_invite_radio_container.disabled_setting_tooltip",
target: "[data-tab-key='invite-email-tab'].disabled",
content: $t({
defaultMessage:
"You do not have permissions to send email invitations in this organization.",
"You do not have permissions to send invite emails in this organization.",
}),
appendTo: () => document.body,
onHidden(instance) {

View File

@ -281,7 +281,7 @@ input::placeholder {
}
&.disabled {
pointer-events: none;
cursor: default;
color: hsl(0deg 0% 80%);
border-color: hsl(0deg 0% 87%);
}

View File

@ -502,3 +502,7 @@
}
}
}
#invite_users_option_tabs_container {
margin-bottom: 20px;
}

View File

@ -12,21 +12,7 @@
</div>
{{/unless}}
<div class="input-group">
<label>{{t "How would you like to invite users?" }}</label>
<div class="invite_type_radio_section prop-element" id="invite-user">
<div id="generate_multiuse_invite_radio_container">
<label class="generate_multiuse_invite_radio_label">
<input type="radio" id="generate_multiuse_invite_radio" name="invite-user" value="generate-multiuse-invite" />
{{t "Generate invite link" }}
</label>
</div>
<div id="email_invite_radio_container">
<label class="email_invite_radio_label">
<input type="radio" id="email_invite_radio" name="invite-user" value="email-invite" />
{{t "Send an email" }}
</label>
</div>
</div>
<div id="invite_users_option_tabs_container" class="new-style"></div>
<div id="invitee_emails_container">
<label for="invitee_emails">{{t "Emails (one on each line or comma-separated)" }}</label>
<div class="pill-container">