) {
if (changedProperties.has("isAddingMember") && this.isAddingMember) {
this.isAddMemberFormVisible = true;
}
if (
changedProperties.has("activePanel") &&
this.activePanel === "members"
) {
this.fetchPendingInvites();
}
}
render() {
return html`
${when(
this.activePanel === "members",
() => html`
${msg("Active Members")}
${msg("Invite New Member")}
`,
() => html` ${this.tabLabels[this.activePanel]}
`
)}
${this.renderTab("information", "settings")}
${this.renderTab("members", "settings/members")}
${this.renderInformation()}
${this.renderMembers()}
`;
}
private renderTab(name: Tab, path: string) {
const isActive = name === this.activePanel;
return html`
${this.tabLabels[name]}
`;
}
private renderInformation() {
return html`
`;
}
private renderMembers() {
const columnWidths = ["100%", "10rem", "1.5rem"];
return html`
[
user.name,
this.renderUserRoleSelect(user),
this.renderRemoveMemberButton(user),
])}
.columnWidths=${columnWidths}
>
${when(
this.pendingInvites.length,
() => html`
${msg("Pending Invites")}
[
user.email,
this.renderUserRole(user),
this.renderRemoveInviteButton(user),
])}
.columnWidths=${columnWidths}
>
`
)}
(this.isAddMemberFormVisible = true)}
@sl-after-hide=${() => (this.isAddMemberFormVisible = false)}
>
${this.isAddMemberFormVisible ? this.renderInviteForm() : ""}
`;
}
private renderUserRole({ role }: User) {
if (isAdmin(role)) return msg("Admin");
if (isCrawler(role)) return msg("Crawler");
return msg("Viewer");
}
private renderUserRoleSelect(user: Member) {
// Consider superadmins owners
const userRole =
user.role === AccessCode.superadmin ? AccessCode.owner : user.role;
return html`
${"Admin"}
${"Crawler"}
${"Viewer"}
`;
}
private renderRemoveMemberButton(member: Member) {
let disableButton = false;
if (member.email === this.userInfo.email) {
const { [this.userInfo.id]: _currentUser, ...otherUsers } =
this.org.users!;
const hasOtherAdmin = Object.values(otherUsers).some(({ role }) =>
isAdmin(role)
);
if (!hasOtherAdmin) {
// Must be another admin in order to remove self
disableButton = true;
}
}
return html`
this.dispatchEvent(
new CustomEvent("org-remove-member", {
detail: { member },
})
)}
>
`;
}
private renderRemoveInviteButton(invite: Invite) {
return html` this.removeInvite(invite)}>
`;
}
private hideInviteDialog() {
this.navTo(`/orgs/${this.orgId}/settings/members`);
}
private renderInviteForm() {
return html`
${msg("Cancel")}
${msg("Invite")}
`;
}
private async checkFormValidity(formEl: HTMLFormElement) {
await this.updateComplete;
return !formEl.querySelector("[data-invalid]");
}
private async getPendingInvites(): Promise {
const data: APIPaginatedList = await this.apiFetch(
`/orgs/${this.org.id}/invites`,
this.authState!
);
return data.items;
}
private async fetchPendingInvites() {
try {
this.pendingInvites = await this.getPendingInvites();
} catch (e: any) {
console.debug(e);
this.notify({
message: msg("Sorry, couldn't retrieve pending invites at this time."),
variant: "danger",
icon: "exclamation-octagon",
});
}
}
private async onOrgNameSubmit(e: SubmitEvent) {
e.preventDefault();
const formEl = e.target as HTMLFormElement;
if (!(await this.checkFormValidity(formEl))) return;
const { orgName } = serialize(formEl);
this.dispatchEvent(
new CustomEvent("org-name-change", {
detail: { value: orgName },
})
);
}
private selectUserRole = (user: User) => (e: Event) => {
this.dispatchEvent(
new CustomEvent("org-user-role-change", {
detail: {
user,
newRole: Number((e.target as HTMLSelectElement).value),
},
})
);
};
async onOrgInviteSubmit(e: SubmitEvent) {
e.preventDefault();
const formEl = e.target as HTMLFormElement;
if (!(await this.checkFormValidity(formEl))) return;
const { inviteEmail, role } = serialize(formEl);
this.isSubmittingInvite = true;
try {
const data = await this.apiFetch(
`/orgs/${this.orgId}/invite`,
this.authState!,
{
method: "POST",
body: JSON.stringify({
email: inviteEmail,
role: Number(role),
}),
}
);
this.notify({
message: msg(str`Successfully invited ${inviteEmail}.`),
variant: "success",
icon: "check2-circle",
});
this.fetchPendingInvites();
this.hideInviteDialog();
} catch (e: any) {
this.notify({
message: e.isApiError
? e.message
: msg("Sorry, couldn't invite user at this time."),
variant: "danger",
icon: "exclamation-octagon",
});
}
this.isSubmittingInvite = false;
}
private async removeInvite(invite: Invite) {
try {
await this.apiFetch(
`/orgs/${this.orgId}/invites/delete`,
this.authState!,
{
method: "POST",
body: JSON.stringify({
email: invite.email,
}),
}
);
this.notify({
message: msg(
str`Successfully removed ${invite.email} from ${this.org.name}.`
),
variant: "success",
icon: "check2-circle",
});
this.pendingInvites = this.pendingInvites.filter(
({ email }) => email !== invite.email
);
} catch (e: any) {
console.debug(e);
this.notify({
message: e.isApiError
? e.message
: msg(str`Sorry, couldn't remove ${invite.email} at this time.`),
variant: "danger",
icon: "exclamation-octagon",
});
}
}
}
customElements.define("btrix-org-settings", OrgSettings);