import { localized, msg, str } from "@lit/localize"; import { Task } from "@lit/task"; import { customElement, property, state } from "lit/decorators.js"; import { renderInviteMessage } from "./ui/inviteMessage"; import type { SignUpSuccessDetail } from "@/features/accounts/sign-up-form"; import type { OrgUpdatedDetail } from "@/pages/invite/ui/org-form"; import type { UserOrg, UserOrgInviteInfo } from "@/types/user"; import AuthService, { type LoggedInEventDetail } from "@/utils/AuthService"; import LiteElement, { html } from "@/utils/LiteElement"; import "./ui/org-form"; @localized() @customElement("btrix-join") export class Join extends LiteElement { @property({ type: String }) token?: string; @property({ type: String }) email?: string; @state() _firstAdminOrgInfo: null | Pick = null; private readonly inviteInfo = new Task(this, { task: async ([token, email]) => { if (!token || !email) throw new Error("Missing args"); const inviteInfo = await this._getInviteInfo({ token, email }); return inviteInfo; }, args: () => [this.token, this.email] as const, }); get _isLoggedIn(): boolean { return Boolean( this.authState && this.email && this.authState.username === this.email, ); } render() { return html`

${msg("Welcome to Browsertrix")}

${this.inviteInfo.render({ complete: (inviteInfo) => renderInviteMessage(inviteInfo, { isExistingUser: false, isOrgMember: this._isLoggedIn, }), })}
${this.inviteInfo.render({ pending: () => html`
`, complete: (inviteInfo) => this._isLoggedIn && this._firstAdminOrgInfo ? html` , ) => { e.stopPropagation(); this.navTo(`/orgs/${e.detail.data.slug}`); }} > ` : html` `, error: (err) => html`
${err instanceof Error ? err.message : err}
${msg("Go to home page")}
`, })}
`; } async _getInviteInfo({ token, email, }: { token: string; email: string; }): Promise { const resp = await fetch( `/api/users/invite/${token}?email=${encodeURIComponent(email)}`, ); switch (resp.status) { case 200: return (await resp.json()) as UserOrgInviteInfo; case 404: throw new Error( msg( "This invite doesn't exist or has expired. Please ask the organization administrator to resend an invitation.", ), ); case 400: throw new Error( msg( str`This is not a valid invite, or it may have expired. If you believe this is an error, please contact ${this.appState.settings?.supportEmail || msg("your Browsertrix administrator")} for help.`, ), ); default: throw new Error( msg( str`Something unexpected went wrong retrieving this invite. Please contact ${this.appState.settings?.supportEmail || msg("your Browsertrix administrator")} for help.`, ), ); } } _onSignUpSuccess(e: CustomEvent) { const inviteInfo = this.inviteInfo.value; if (!inviteInfo) return; if (inviteInfo.firstOrgAdmin) { const { orgName, orgSlug } = e.detail; this._firstAdminOrgInfo = { id: inviteInfo.oid, name: orgName || inviteInfo.orgName || "", slug: orgSlug || inviteInfo.orgSlug || "", }; } } _onAuthenticated(event: CustomEvent) { this.dispatchEvent( AuthService.createLoggedInEvent({ ...event.detail, api: true, // Prevent default navigation }), ); const inviteInfo = this.inviteInfo.value; if (!inviteInfo?.firstOrgAdmin) { if (inviteInfo?.orgSlug) { this.navTo(`/orgs/${inviteInfo.orgSlug}`); } else { this.navTo(this.orgBasePath); } } } }