diff --git a/frontend/src/components/sign-up-form.ts b/frontend/src/components/sign-up-form.ts index 81978d72..6151c8d3 100644 --- a/frontend/src/components/sign-up-form.ts +++ b/frontend/src/components/sign-up-form.ts @@ -50,8 +50,10 @@ export class SignUpForm extends LiteElement {
${this.email ? html` - ${msg("Joining as")} - ${this.email} +
+ ${msg("Joining as")} +
+
${this.email}
`; } if (this.isRegistrationEnabled) { return html``; } diff --git a/frontend/src/pages/accept-invite.ts b/frontend/src/pages/accept-invite.ts index 5bfac194..856a4ac2 100644 --- a/frontend/src/pages/accept-invite.ts +++ b/frontend/src/pages/accept-invite.ts @@ -1,9 +1,8 @@ import { state, property } from "lit/decorators.js"; -import { msg, localized } from "@lit/localize"; +import { msg, str, localized } from "@lit/localize"; import LiteElement, { html } from "../utils/LiteElement"; -import type { AuthState, LoggedInEvent } from "../utils/AuthService"; -import AuthService from "../utils/AuthService"; +import type { AuthState } from "../utils/AuthService"; import { DASHBOARD_ROUTE } from "../routes"; @localized() @@ -20,6 +19,17 @@ export class AcceptInvite extends LiteElement { @state() serverError?: string; + @state() + private inviteInfo: { + inviterEmail: string; + inviterName: string; + archiveName: string; + } = { + inviterEmail: "", + inviterName: "", + archiveName: "", + }; + connectedCallback(): void { if (this.token && this.email) { super.connectedCallback(); @@ -35,7 +45,9 @@ export class AcceptInvite extends LiteElement { } firstUpdated() { - if (!this.isLoggedIn) { + if (this.isLoggedIn) { + this.getInviteInfo(); + } else { this.dispatchEvent( new CustomEvent("notify", { detail: { @@ -60,7 +72,7 @@ export class AcceptInvite extends LiteElement { if (this.serverError) { serverError = html` -
+
${this.serverError} @@ -68,27 +80,69 @@ export class AcceptInvite extends LiteElement { `; } + const hasInviteInfo = Boolean(this.inviteInfo.inviterEmail); + const placeholder = html` `; + + if (serverError && !hasInviteInfo) { + return serverError; + } + return html` -
+
${serverError}
-

- ${msg("Join archive")} -

- - +
+ ${msg("Invited by ")} + ${this.inviteInfo.inviterName || + this.inviteInfo.inviterEmail || + placeholder} +
+

+ ${msg( + html`You've been invited to join + ${hasInviteInfo + ? this.inviteInfo.archiveName || msg("Browsertrix Cloud") + : placeholder}` + )} +

- ${msg("Accept invitation")} + ${msg("Decline")}
`; } + private async getInviteInfo() { + if (!this.authState) return; + + try { + const data = await this.apiFetch( + `/users/me/invite/${this.token}`, + this.authState + ); + + this.inviteInfo = { + inviterEmail: data.inviterEmail, + inviterName: data.inviterName, + archiveName: data.archiveName, + }; + } catch { + this.serverError = msg("This invitation is not valid"); + } + } + private async onAccept() { if (!this.authState || !this.isLoggedIn) { // TODO handle error @@ -109,8 +163,7 @@ export class AcceptInvite extends LiteElement { this.dispatchEvent( new CustomEvent("notify", { detail: { - // TODO archive details - message: msg("You've joined the archive."), + message: msg(str`You've joined ${this.inviteInfo.archiveName}.`), type: "success", icon: "check2-circle", }, @@ -120,10 +173,26 @@ export class AcceptInvite extends LiteElement { this.navTo(DASHBOARD_ROUTE); } catch (err: any) { if (err.isApiError && err.message === "Invalid Invite Code") { - this.serverError = msg("This invitation is not valid."); + this.serverError = msg("This invitation is not valid"); } else { this.serverError = msg("Something unexpected went wrong"); } } } + + private onDecline() { + this.dispatchEvent( + new CustomEvent("notify", { + detail: { + message: msg( + str`You've declined to join ${this.inviteInfo.archiveName}.` + ), + type: "info", + icon: "info-circle", + }, + }) + ); + + this.navTo(DASHBOARD_ROUTE); + } } diff --git a/frontend/src/pages/join.ts b/frontend/src/pages/join.ts index e73e65c3..b346e5c7 100644 --- a/frontend/src/pages/join.ts +++ b/frontend/src/pages/join.ts @@ -1,5 +1,5 @@ import { state, property } from "lit/decorators.js"; -import { msg, localized } from "@lit/localize"; +import { msg, str, localized } from "@lit/localize"; import LiteElement, { html } from "../utils/LiteElement"; import type { LoggedInEvent } from "../utils/AuthService"; @@ -14,7 +14,18 @@ export class Join extends LiteElement { email?: string; @state() - serverError?: string; + private serverError?: string; + + @state() + private inviteInfo: { + inviterEmail: string; + inviterName: string; + archiveName: string; + } = { + inviterEmail: "", + inviterName: "", + archiveName: "", + }; connectedCallback(): void { if (this.token && this.email) { @@ -24,16 +35,46 @@ export class Join extends LiteElement { } } + firstUpdated() { + this.getInviteInfo(); + } + render() { + if (this.serverError) { + return html`${this.serverError}`; + } + + const hasInviteInfo = Boolean(this.inviteInfo.inviterEmail); + const placeholder = html` `; + return html` -
-
-

- ${msg("Join Browsertrix Cloud")} -

- - +
+
+
+ ${msg("Invited by ")} + ${this.inviteInfo.inviterName || + this.inviteInfo.inviterEmail || + placeholder} +
+

+ ${msg( + html`You've been invited to join + ${hasInviteInfo + ? this.inviteInfo.archiveName || msg("Browsertrix Cloud") + : placeholder}` + )} +

+
+