add dialog
This commit is contained in:
parent
ebb9dc826a
commit
13b6a5b15f
@ -1,16 +1,19 @@
|
|||||||
import { localized, msg, str } from "@lit/localize";
|
import { localized, msg, str } from "@lit/localize";
|
||||||
import type { SlInput } from "@shoelace-style/shoelace";
|
import type { SlInput } from "@shoelace-style/shoelace";
|
||||||
import { type TemplateResult } from "lit";
|
import { html, type TemplateResult } from "lit";
|
||||||
import { customElement, property } from "lit/decorators.js";
|
import { customElement, property, query } from "lit/decorators.js";
|
||||||
import { when } from "lit/directives/when.js";
|
import { when } from "lit/directives/when.js";
|
||||||
|
|
||||||
|
import { TailwindElement } from "@/classes/TailwindElement";
|
||||||
|
import type { Dialog } from "@/components/ui/dialog";
|
||||||
|
import { APIController } from "@/controllers/api";
|
||||||
|
import { NavigateController } from "@/controllers/navigate";
|
||||||
import type { CurrentUser, UserOrg } from "@/types/user";
|
import type { CurrentUser, UserOrg } from "@/types/user";
|
||||||
import LiteElement, { html } from "@/utils/LiteElement";
|
|
||||||
import type { OrgData } from "@/utils/orgs";
|
import type { OrgData } from "@/utils/orgs";
|
||||||
|
|
||||||
@localized()
|
@localized()
|
||||||
@customElement("btrix-orgs-list")
|
@customElement("btrix-orgs-list")
|
||||||
export class OrgsList extends LiteElement {
|
export class OrgsList extends TailwindElement {
|
||||||
@property({ type: Object })
|
@property({ type: Object })
|
||||||
userInfo?: CurrentUser;
|
userInfo?: CurrentUser;
|
||||||
|
|
||||||
@ -23,6 +26,15 @@ export class OrgsList extends LiteElement {
|
|||||||
@property({ type: Object })
|
@property({ type: Object })
|
||||||
currOrg?: OrgData | null = null;
|
currOrg?: OrgData | null = null;
|
||||||
|
|
||||||
|
@query("#orgDeleteDialog")
|
||||||
|
orgDeleteDialog?: Dialog | null;
|
||||||
|
|
||||||
|
@query("#orgQuotaDialog")
|
||||||
|
orgQuotaDialog?: Dialog | null;
|
||||||
|
|
||||||
|
private readonly api = new APIController(this);
|
||||||
|
private readonly navigate = new NavigateController(this);
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (this.skeleton) {
|
if (this.skeleton) {
|
||||||
return this.renderSkeleton();
|
return this.renderSkeleton();
|
||||||
@ -33,17 +45,108 @@ export class OrgsList extends LiteElement {
|
|||||||
return html`
|
return html`
|
||||||
<ul class="overflow-hidden rounded-lg border">
|
<ul class="overflow-hidden rounded-lg border">
|
||||||
${this.orgList?.map(this.renderOrg(defaultOrg))}
|
${this.orgList?.map(this.renderOrg(defaultOrg))}
|
||||||
|
${this.renderOrgDelete()}
|
||||||
${this.renderOrgQuotas()}
|
${this.renderOrgQuotas()}
|
||||||
</ul>
|
</ul>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private renderOrgDelete() {
|
||||||
|
return html`
|
||||||
|
<btrix-dialog
|
||||||
|
class="[--width:36rem]"
|
||||||
|
id="orgDeleteDialog"
|
||||||
|
.label=${msg(str`Confirm Org Deletion: ${this.currOrg?.name || ""}`)}
|
||||||
|
@sl-after-hide=${() => (this.currOrg = null)}
|
||||||
|
>
|
||||||
|
${when(this.currOrg, (org) => {
|
||||||
|
const confirmationStr = msg(str`Delete ${org.name}`);
|
||||||
|
return html`
|
||||||
|
<p class="mb-3">
|
||||||
|
${msg(
|
||||||
|
html`Are you sure you want to delete
|
||||||
|
<a
|
||||||
|
class="font-semibold text-primary"
|
||||||
|
href="/orgs/${org.slug}"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
${org.name}
|
||||||
|
<sl-icon
|
||||||
|
name="box-arrow-up-right"
|
||||||
|
label=${msg("Open in new window")}
|
||||||
|
></sl-icon> </a
|
||||||
|
>? This cannot be undone.`,
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
<ul class="mb-3 text-neutral-600">
|
||||||
|
<li>${msg(str`Slug: ${org.slug}`)}</li>
|
||||||
|
<li>
|
||||||
|
${msg(
|
||||||
|
str`Members: ${Object.keys(org.users || {}).length.toLocaleString()}`,
|
||||||
|
)}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p class="mb-3">
|
||||||
|
${msg(
|
||||||
|
html`Deleting an org will delete all
|
||||||
|
<strong class="font-semibold">
|
||||||
|
<sl-format-bytes value=${org.bytesStored}></sl-format-bytes>
|
||||||
|
</strong>
|
||||||
|
of data associated with the org.`,
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
<ul class="mb-3 text-neutral-600">
|
||||||
|
<li>
|
||||||
|
${msg(
|
||||||
|
html`Crawls:
|
||||||
|
<sl-format-bytes
|
||||||
|
value=${org.bytesStoredCrawls}
|
||||||
|
></sl-format-bytes>`,
|
||||||
|
)}
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
${msg(
|
||||||
|
html`Uploads:
|
||||||
|
<sl-format-bytes
|
||||||
|
value=${org.bytesStoredUploads}
|
||||||
|
></sl-format-bytes>`,
|
||||||
|
)}
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
${msg(
|
||||||
|
html`Profiles:
|
||||||
|
<sl-format-bytes
|
||||||
|
value=${org.bytesStoredProfiles}
|
||||||
|
></sl-format-bytes>`,
|
||||||
|
)}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<sl-divider></sl-divider>
|
||||||
|
<sl-input placeholder=${confirmationStr}>
|
||||||
|
<strong slot="label" class="font-semibold">
|
||||||
|
${msg(str`Type "${confirmationStr}" to confirm`)}
|
||||||
|
</strong>
|
||||||
|
</sl-input>
|
||||||
|
`;
|
||||||
|
})}
|
||||||
|
<div slot="footer" class="flex justify-end">
|
||||||
|
<sl-button
|
||||||
|
size="small"
|
||||||
|
@click="${this.onSubmitQuotas}"
|
||||||
|
variant="danger"
|
||||||
|
>${msg("Delete Org")}
|
||||||
|
</sl-button>
|
||||||
|
</div>
|
||||||
|
</btrix-dialog>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
private renderOrgQuotas() {
|
private renderOrgQuotas() {
|
||||||
return html`
|
return html`
|
||||||
<btrix-dialog
|
<btrix-dialog
|
||||||
|
id="orgQuotaDialog"
|
||||||
.label=${msg(str`Quotas for: ${this.currOrg?.name || ""}`)}
|
.label=${msg(str`Quotas for: ${this.currOrg?.name || ""}`)}
|
||||||
.open=${!!this.currOrg}
|
@sl-after-hide=${() => (this.currOrg = null)}
|
||||||
@sl-request-close=${() => (this.currOrg = null)}
|
|
||||||
>
|
>
|
||||||
${when(this.currOrg?.quotas, (quotas) =>
|
${when(this.currOrg?.quotas, (quotas) =>
|
||||||
Object.entries(quotas).map(([key, value]) => {
|
Object.entries(quotas).map(([key, value]) => {
|
||||||
@ -72,6 +175,7 @@ export class OrgsList extends LiteElement {
|
|||||||
label = msg("Unlabeled");
|
label = msg("Unlabeled");
|
||||||
}
|
}
|
||||||
return html` <sl-input
|
return html` <sl-input
|
||||||
|
class="mb-3 last:mb-0"
|
||||||
name=${key}
|
name=${key}
|
||||||
label=${label}
|
label=${label}
|
||||||
value=${value}
|
value=${value}
|
||||||
@ -110,18 +214,6 @@ export class OrgsList extends LiteElement {
|
|||||||
new CustomEvent("update-quotas", { detail: this.currOrg }),
|
new CustomEvent("update-quotas", { detail: this.currOrg }),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
this.currOrg = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private showQuotas(org: OrgData) {
|
|
||||||
const stop = (e: Event) => {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
this.currOrg = org;
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
return stop;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly renderOrg = (defaultOrg?: UserOrg) => (org: OrgData) => {
|
private readonly renderOrg = (defaultOrg?: UserOrg) => (org: OrgData) => {
|
||||||
@ -158,12 +250,31 @@ export class OrgsList extends LiteElement {
|
|||||||
? msg(`1 member`)
|
? msg(`1 member`)
|
||||||
: msg(str`${memberCount} members`)}
|
: msg(str`${memberCount} members`)}
|
||||||
</div>
|
</div>
|
||||||
<sl-icon-button
|
<btrix-overflow-dropdown
|
||||||
name="gear"
|
@click=${(e: MouseEvent) => e.stopPropagation()}
|
||||||
slot="prefix"
|
>
|
||||||
label=${msg("Edit org quotas")}
|
<sl-menu>
|
||||||
@click="${this.showQuotas(org)}"
|
<sl-menu-item
|
||||||
></sl-icon-button>
|
@click=${() => {
|
||||||
|
this.currOrg = org;
|
||||||
|
void this.orgQuotaDialog?.show();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<sl-icon slot="prefix" name="gear"></sl-icon>
|
||||||
|
${msg("Edit Quotas")}
|
||||||
|
</sl-menu-item>
|
||||||
|
<sl-menu-item
|
||||||
|
style="--sl-color-neutral-700: var(--danger)"
|
||||||
|
@click=${() => {
|
||||||
|
this.currOrg = org;
|
||||||
|
void this.orgDeleteDialog?.show();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<sl-icon slot="prefix" name="trash3"></sl-icon>
|
||||||
|
${msg("Delete Org")}
|
||||||
|
</sl-menu-item>
|
||||||
|
</sl-menu>
|
||||||
|
</btrix-overflow-dropdown>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
`;
|
`;
|
||||||
@ -180,7 +291,7 @@ export class OrgsList extends LiteElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private makeOnOrgClick(org: OrgData) {
|
private makeOnOrgClick(org: OrgData) {
|
||||||
const navigate = () => this.navTo(`/orgs/${org.slug}`);
|
const navigate = () => this.navigate.to(`/orgs/${org.slug}`);
|
||||||
|
|
||||||
if (typeof window.getSelection !== "undefined") {
|
if (typeof window.getSelection !== "undefined") {
|
||||||
return () => {
|
return () => {
|
||||||
|
@ -19,6 +19,9 @@ export type OrgData = {
|
|||||||
slug: string;
|
slug: string;
|
||||||
quotas?: Record<string, number>;
|
quotas?: Record<string, number>;
|
||||||
bytesStored: number;
|
bytesStored: number;
|
||||||
|
bytesStoredCrawls: number;
|
||||||
|
bytesStoredUploads: number;
|
||||||
|
bytesStoredProfiles: number;
|
||||||
usage: { [key: YearMonth]: number } | null;
|
usage: { [key: YearMonth]: number } | null;
|
||||||
crawlExecSeconds?: { [key: YearMonth]: number };
|
crawlExecSeconds?: { [key: YearMonth]: number };
|
||||||
monthlyExecSeconds?: { [key: YearMonth]: number };
|
monthlyExecSeconds?: { [key: YearMonth]: number };
|
||||||
|
Loading…
Reference in New Issue
Block a user