Show invite message to super admin & layout fixes (#181)

This commit is contained in:
sua yoo 2022-03-02 18:09:26 -08:00 committed by GitHub
parent fe31f551b2
commit c18418ff09
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 180 additions and 52 deletions

View File

@ -14,12 +14,12 @@ type LocaleNames = {
@localized()
export class LocalePicker extends LitElement {
@state()
private localeNames?: LocaleNames;
private localeNames: LocaleNames = {} as LocaleNames;
private setLocaleName = (locale: LocaleCode) => {
this.localeNames![locale] = new Intl.DisplayNames([locale], {
this.localeNames[locale] = new Intl.DisplayNames([locale], {
type: "language",
}).of(locale);
}).of(locale)!;
};
async firstUpdated() {
@ -63,22 +63,33 @@ export class LocalePicker extends LitElement {
const selectedLocale = getLocale();
return html`
<sl-select value=${selectedLocale} @sl-change=${this.localeChanged}>
${allLocales.map(
(locale) =>
html`<sl-menu-item
value=${locale}
?selected=${locale === selectedLocale}
>
${this.localeNames![locale]}
</sl-menu-item>`
)}
</sl-select>
<sl-dropdown
value=${selectedLocale}
@sl-select=${this.localeChanged}
placement="top-end"
distance="4"
hoist
>
<sl-button slot="trigger" size="small" caret
>${this.localeNames[selectedLocale as LocaleCode]}</sl-button
>
<sl-menu>
${allLocales.map(
(locale) =>
html`<sl-menu-item
value=${locale}
?checked=${locale === selectedLocale}
>
${this.localeNames[locale]}
</sl-menu-item>`
)}
</sl-menu>
</sl-dropdown>
`;
}
async localeChanged(event: Event) {
const newLocale = (event.target as HTMLSelectElement).value as LocaleCode;
async localeChanged(event: CustomEvent) {
const newLocale = event.detail.item.value as LocaleCode;
if (newLocale !== getLocale()) {
const url = new URL(window.location.href);

View File

@ -194,9 +194,7 @@ export class App extends LiteElement {
<div class="min-w-screen min-h-screen flex flex-col">
${this.renderNavBar()}
<main class="relative flex-auto flex">${this.renderPage()}</main>
<footer class="flex justify-center p-4 border-t">
<btrix-locale-picker></btrix-locale-picker>
</footer>
<div class="border-t border-neutral-100">${this.renderFooter()}</div>
</div>
<sl-dialog
@ -217,34 +215,61 @@ export class App extends LiteElement {
>
<div>
<a href="/archives" @click="${this.navLink}"
><h1 class="text-base">${msg("Browsertrix Cloud")}</h1></a
><h1 class="text-sm font-medium">
${msg("Browsertrix Cloud")}
</h1></a
>
</div>
<div class="grid grid-flow-col gap-5 items-center">
${this.authService.authState
? html` <sl-dropdown placement="bottom-end">
<div class="p-2" role="button" slot="trigger">
${this.userInfo?.name || this.userInfo?.email}
<span class="text-xs"
><sl-icon name="chevron-down"></sl-icon
></span>
</div>
<sl-menu>
<sl-icon-button
slot="trigger"
name="person-circle"
style="font-size: 1.5rem;"
></sl-icon-button>
<sl-menu class="w-60 min-w-min max-w-full">
<div class="px-7 py-2">
${this.userInfo?.isAdmin
? html`
<div class="mb-2">
<sl-tag
class="uppercase"
type="primary"
size="small"
>${msg("admin")}</sl-tag
>
</div>
`
: ""}
<div class="font-medium text-neutral-700">
${this.userInfo?.name}
</div>
<div class="text-sm text-neutral-500">
${this.userInfo?.email}
</div>
</div>
<sl-divider></sl-divider>
<sl-menu-item
@click=${() => this.navigate(ROUTES.accountSettings)}
>
<sl-icon slot="prefix" name="gear"></sl-icon>
${msg("Your account")}
</sl-menu-item>
${this.userInfo?.isAdmin
? html` <sl-menu-item
@click=${() => this.navigate(ROUTES.usersInvite)}
>
<sl-icon slot="prefix" name="person-plus"></sl-icon>
${msg("Invite Users")}
</sl-menu-item>`
: ""}
<sl-menu-item @click="${this.onLogOut}"
>${msg("Log Out")}</sl-menu-item
>
<sl-divider></sl-divider>
<sl-menu-item @click="${this.onLogOut}">
<sl-icon slot="prefix" name="box-arrow-right"></sl-icon>
${msg("Log Out")}
</sl-menu-item>
</sl-menu>
</sl-dropdown>`
: html`
@ -266,17 +291,36 @@ export class App extends LiteElement {
`;
}
renderFooter() {
return html`
<footer
class="w-full max-w-screen-lg mx-auto p-3 box-border flex justify-between"
>
<div>
<sl-icon-button
name="github"
href="https://github.com/webrecorder/browsertrix-cloud"
target="_blank"
></sl-icon-button>
</div>
<div>
<btrix-locale-picker></btrix-locale-picker>
</div>
</footer>
`;
}
renderPage() {
switch (this.viewState.route) {
case "signUp": {
if (!this.isAppSettingsLoaded) {
return html`<div
class="w-full md:bg-gray-50 flex items-center justify-center"
class="w-full md:bg-neutral-50 flex items-center justify-center"
></div>`;
}
if (this.isRegistrationEnabled) {
return html`<btrix-sign-up
class="w-full md:bg-gray-50 flex items-center justify-center"
class="w-full md:bg-neutral-50 flex items-center justify-center"
@navigate="${this.onNavigateTo}"
@logged-in="${this.onLoggedIn}"
@log-out="${this.onLogOut}"
@ -289,7 +333,7 @@ export class App extends LiteElement {
case "verify":
return html`<btrix-verify
class="w-full md:bg-gray-50 flex items-center justify-center"
class="w-full md:bg-neutral-50 flex items-center justify-center"
token="${this.viewState.params.token}"
@navigate="${this.onNavigateTo}"
@notify="${this.onNotify}"
@ -300,7 +344,7 @@ export class App extends LiteElement {
case "join":
return html`<btrix-join
class="w-full md:bg-gray-50 flex items-center justify-center"
class="w-full md:bg-neutral-50 flex items-center justify-center"
@navigate="${this.onNavigateTo}"
@logged-in="${this.onLoggedIn}"
token="${this.viewState.params.token}"
@ -309,7 +353,7 @@ export class App extends LiteElement {
case "acceptInvite":
return html`<btrix-accept-invite
class="w-full md:bg-gray-50 flex items-center justify-center"
class="w-full md:bg-neutral-50 flex items-center justify-center"
@navigate="${this.onNavigateTo}"
@logged-in="${this.onLoggedIn}"
@notify="${this.onNotify}"
@ -322,7 +366,7 @@ export class App extends LiteElement {
case "loginWithRedirect":
case "forgotPassword":
return html`<btrix-log-in
class="w-full md:bg-gray-50 flex items-center justify-center"
class="w-full md:bg-neutral-50 flex items-center justify-center"
@navigate=${this.onNavigateTo}
@logged-in=${this.onLoggedIn}
.authState=${this.authService.authState}
@ -332,7 +376,7 @@ export class App extends LiteElement {
case "resetPassword":
return html`<btrix-reset-password
class="w-full md:bg-gray-50 flex items-center justify-center"
class="w-full md:bg-neutral-50 flex items-center justify-center"
@navigate=${this.onNavigateTo}
@logged-in=${this.onLoggedIn}
.authState=${this.authService.authState}
@ -352,7 +396,7 @@ export class App extends LiteElement {
case "archives":
return html`<btrix-archives
class="w-full max-w-screen-lg mx-auto p-2 md:py-8 box-border"
class="w-full md:bg-neutral-50"
@navigate="${this.onNavigateTo}"
@need-login="${this.onNeedLogin}"
.authState="${this.authService.authState}"
@ -412,7 +456,7 @@ export class App extends LiteElement {
renderNotFoundPage() {
return html`<btrix-not-found
class="w-full md:bg-gray-50 flex items-center justify-center"
class="w-full md:bg-neutral-50 flex items-center justify-center"
></btrix-not-found>`;
}

View File

@ -18,34 +18,78 @@ export class Archives extends LiteElement {
userInfo?: CurrentUser;
@state()
archiveList?: ArchiveData[];
private archiveList?: ArchiveData[];
@state()
private isInviteComplete?: boolean;
async firstUpdated() {
this.archiveList = await this.getArchives();
}
render() {
if (!this.archiveList) {
return html`<div
class="w-full flex items-center justify-center my-24 text-4xl"
>
<sl-spinner></sl-spinner>
if (!this.archiveList || !this.userInfo) {
return html`
<div class="flex items-center justify-center my-24 text-4xl">
<sl-spinner></sl-spinner>
</div>
`;
}
if (this.userInfo.isAdmin && !this.archiveList.length) {
return html`
<div class="bg-white">
<header
class="w-full max-w-screen-lg mx-auto px-3 py-4 box-border md:py-8"
>
<h1 class="text-2xl font-medium">${msg("Archives")}</h1>
<p class="mt-4 text-neutral-600">
${msg("Invite users to start archiving.")}
</p>
</header>
<hr />
</div>
<main class="w-full max-w-screen-lg mx-auto px-3 py-4 box-border">
${this.renderAdminOnboarding()}
</main>
`;
}
return html`
<div class="bg-white">
<header
class="w-full max-w-screen-lg mx-auto px-3 py-4 box-border md:py-8"
>
<h1 class="text-2xl font-medium">${msg("Archives")}</h1>
</header>
<hr />
</div>
<main class="w-full max-w-screen-lg mx-auto px-3 py-4 box-border">
${this.renderArchives()}
</main>
`;
}
private renderArchives() {
if (!this.archiveList?.length) {
return html`<div class="border rounded-lg bg-white p-4 md:p-8">
<p class="text-neutral-400 text-center">
${msg("You don't have any archives.")}
</p>
</div>`;
}
return html`<div class="grid gap-4">
<h1 class="text-xl font-bold">${msg("Archives")}</h1>
return html`
<ul class="border rounded-lg overflow-hidden">
${this.archiveList.map(
(archive, i) =>
(archive) =>
html`
<li
class="p-3 md:p-6 hover:bg-gray-50${i > 0 ? " border-t" : ""}"
class="p-3 md:p-6 bg-white border-t first:border-t-0 text-primary hover:text-indigo-400"
role="button"
@click=${this.makeOnArchiveClick(archive)}
>
<span class="text-primary font-medium mr-2"
<span class="font-medium mr-2 transition-colors"
>${archive.name}</span
>
${this.userInfo &&
@ -59,7 +103,33 @@ export class Archives extends LiteElement {
`
)}
</ul>
</div>`;
`;
}
private renderAdminOnboarding() {
if (this.isInviteComplete) {
return html`
<div class="border rounded-lg bg-white p-4 md:p-8">
<h2 class="text-2xl font-medium mb-4">${msg("Invite a User")}</h2>
<sl-button @click=${() => (this.isInviteComplete = false)}
>${msg("Send another invite")}</sl-button
>
</div>
`;
}
return html`
<div class="border rounded-lg bg-white p-4 md:p-8">
<h2 class="text-2xl font-medium mb-4">${msg("Invite a User")}</h2>
<p class="mb-4 text-neutral-600 text-sm">
${msg("Each user will manage their own archive.")}
</p>
<btrix-invite-form
.authState=${this.authState}
@success=${() => (this.isInviteComplete = true)}
></btrix-invite-form>
</div>
`;
}
async getArchives(): Promise<ArchiveData[]> {

View File

@ -20,6 +20,9 @@ import(
import(
/* webpackChunkName: "shoelace" */ "@shoelace-style/shoelace/dist/components/dialog/dialog"
);
import(
/* webpackChunkName: "shoelace" */ "@shoelace-style/shoelace/dist/components/divider/divider"
);
import(
/* webpackChunkName: "shoelace" */ "@shoelace-style/shoelace/dist/components/form/form"
);