Allow admin users to change org name (#506)
This commit is contained in:
parent
0486d50fe9
commit
7dc85cc33c
@ -583,6 +583,7 @@ export class App extends LiteElement {
|
|||||||
class="w-full"
|
class="w-full"
|
||||||
@navigate=${this.onNavigateTo}
|
@navigate=${this.onNavigateTo}
|
||||||
@need-login=${this.onNeedLogin}
|
@need-login=${this.onNeedLogin}
|
||||||
|
@update-user-info=${this.updateUserInfo}
|
||||||
@notify="${this.onNotify}"
|
@notify="${this.onNotify}"
|
||||||
.authState=${this.authService.authState}
|
.authState=${this.authService.authState}
|
||||||
.userInfo=${this.userInfo}
|
.userInfo=${this.userInfo}
|
||||||
@ -681,7 +682,10 @@ export class App extends LiteElement {
|
|||||||
tabName: "browser-profiles",
|
tabName: "browser-profiles",
|
||||||
label: msg("Browser Profiles"),
|
label: msg("Browser Profiles"),
|
||||||
})}
|
})}
|
||||||
${this.renderNavTab({ tabName: "members", label: msg("Members") })}
|
${this.renderNavTab({
|
||||||
|
tabName: "settings",
|
||||||
|
label: msg("Org Settings"),
|
||||||
|
})}
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
import { state, property } from "lit/decorators.js";
|
import { state, property } from "lit/decorators.js";
|
||||||
import { msg, localized, str } from "@lit/localize";
|
import { msg, localized, str } from "@lit/localize";
|
||||||
|
import { when } from "lit/directives/when.js";
|
||||||
|
import { serialize } from "@shoelace-style/shoelace/dist/utilities/form.js";
|
||||||
|
|
||||||
import type { ViewState } from "../../utils/APIRouter";
|
import type { ViewState } from "../../utils/APIRouter";
|
||||||
import type { AuthState } from "../../utils/AuthService";
|
import type { AuthState } from "../../utils/AuthService";
|
||||||
@ -16,12 +18,13 @@ import "./crawls-list";
|
|||||||
import "./browser-profiles-detail";
|
import "./browser-profiles-detail";
|
||||||
import "./browser-profiles-list";
|
import "./browser-profiles-list";
|
||||||
import "./browser-profiles-new";
|
import "./browser-profiles-new";
|
||||||
|
import { SlButton } from "@shoelace-style/shoelace";
|
||||||
|
|
||||||
export type OrgTab =
|
export type OrgTab =
|
||||||
| "crawls"
|
| "crawls"
|
||||||
| "crawl-configs"
|
| "crawl-configs"
|
||||||
| "browser-profiles"
|
| "browser-profiles"
|
||||||
| "members";
|
| "settings";
|
||||||
|
|
||||||
const defaultTab = "crawls";
|
const defaultTab = "crawls";
|
||||||
|
|
||||||
@ -71,6 +74,12 @@ export class Org extends LiteElement {
|
|||||||
@state()
|
@state()
|
||||||
private successfullyInvitedEmail?: string;
|
private successfullyInvitedEmail?: string;
|
||||||
|
|
||||||
|
@state()
|
||||||
|
private isEditingOrgName = false;
|
||||||
|
|
||||||
|
@state()
|
||||||
|
private isSavingOrgName = false;
|
||||||
|
|
||||||
async willUpdate(changedProperties: Map<string, any>) {
|
async willUpdate(changedProperties: Map<string, any>) {
|
||||||
if (changedProperties.has("orgId") && this.orgId) {
|
if (changedProperties.has("orgId") && this.orgId) {
|
||||||
try {
|
try {
|
||||||
@ -125,11 +134,11 @@ export class Org extends LiteElement {
|
|||||||
case "browser-profiles":
|
case "browser-profiles":
|
||||||
tabPanelContent = this.renderBrowserProfiles();
|
tabPanelContent = this.renderBrowserProfiles();
|
||||||
break;
|
break;
|
||||||
case "members":
|
case "settings":
|
||||||
if (this.isAddingMember) {
|
if (this.isAddingMember) {
|
||||||
tabPanelContent = this.renderAddMember();
|
tabPanelContent = this.renderAddMember();
|
||||||
} else {
|
} else {
|
||||||
tabPanelContent = this.renderMembers();
|
tabPanelContent = this.renderOrgSettings();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -225,6 +234,74 @@ export class Org extends LiteElement {
|
|||||||
></btrix-browser-profiles-list>`;
|
></btrix-browser-profiles-list>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private renderOrgSettings() {
|
||||||
|
return html`<btrix-section-heading
|
||||||
|
>${msg("Org Information")}</btrix-section-heading
|
||||||
|
>
|
||||||
|
<section class="mt-5 mb-10">${this.renderOrgName()}</section>
|
||||||
|
<btrix-section-heading>${msg("Org Members")}</btrix-section-heading>
|
||||||
|
<section class="mt-5">${this.renderMembers()}</section>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private renderOrgName() {
|
||||||
|
if (!this.org || !this.userInfo) return;
|
||||||
|
const memberInfo = (this.org.users ?? {})[this.userInfo.id];
|
||||||
|
if (!memberInfo || !isOwner(memberInfo.role)) {
|
||||||
|
return html`
|
||||||
|
<sl-input
|
||||||
|
label=${msg("Org Name")}
|
||||||
|
value=${this.org.name}
|
||||||
|
readonly
|
||||||
|
></sl-input>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return html`<form
|
||||||
|
@submit=${this.onOrgNameSubmit}
|
||||||
|
@reset=${() => (this.isEditingOrgName = false)}
|
||||||
|
>
|
||||||
|
<div class="flex items-end">
|
||||||
|
<div class="flex-1 mr-3">
|
||||||
|
<sl-input
|
||||||
|
name="orgName"
|
||||||
|
label=${msg("Org Name")}
|
||||||
|
autocomplete="off"
|
||||||
|
value=${this.org.name}
|
||||||
|
?readonly=${!this.isEditingOrgName}
|
||||||
|
?required=${this.isEditingOrgName}
|
||||||
|
></sl-input>
|
||||||
|
</div>
|
||||||
|
<div class="flex-0">
|
||||||
|
${when(
|
||||||
|
this.isEditingOrgName,
|
||||||
|
() => html`
|
||||||
|
<sl-button type="reset" class="mr-1">${msg("Cancel")}</sl-button>
|
||||||
|
<sl-button
|
||||||
|
type="submit"
|
||||||
|
variant="primary"
|
||||||
|
?disabled=${this.isSavingOrgName}
|
||||||
|
?loading=${this.isSavingOrgName}
|
||||||
|
>${msg("Save Changes")}</sl-button
|
||||||
|
>
|
||||||
|
`,
|
||||||
|
() => html`
|
||||||
|
<sl-button
|
||||||
|
@click=${(e: MouseEvent) => {
|
||||||
|
this.isEditingOrgName = true;
|
||||||
|
(e.target as SlButton)
|
||||||
|
.closest("form")
|
||||||
|
?.querySelector("sl-input")
|
||||||
|
?.focus();
|
||||||
|
}}
|
||||||
|
>${msg("Edit")}</sl-button
|
||||||
|
>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>`;
|
||||||
|
}
|
||||||
|
|
||||||
private renderMembers() {
|
private renderMembers() {
|
||||||
if (!this.org!.users) return;
|
if (!this.org!.users) return;
|
||||||
|
|
||||||
@ -245,8 +322,7 @@ export class Org extends LiteElement {
|
|||||||
|
|
||||||
<div class="text-right">
|
<div class="text-right">
|
||||||
<sl-button
|
<sl-button
|
||||||
href=${`/orgs/${this.orgId}/members/add-member`}
|
href=${`/orgs/${this.orgId}/settings/add-member`}
|
||||||
variant="primary"
|
|
||||||
@click=${this.navLink}
|
@click=${this.navLink}
|
||||||
>${msg("Add Member")}</sl-button
|
>${msg("Add Member")}</sl-button
|
||||||
>
|
>
|
||||||
@ -298,7 +374,7 @@ export class Org extends LiteElement {
|
|||||||
class="inline-block align-middle"
|
class="inline-block align-middle"
|
||||||
></sl-icon>
|
></sl-icon>
|
||||||
<span class="inline-block align-middle"
|
<span class="inline-block align-middle"
|
||||||
>${msg("Back to Members")}</span
|
>${msg("Back to Settings")}</span
|
||||||
>
|
>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@ -321,6 +397,45 @@ export class Org extends LiteElement {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async onOrgNameSubmit(e: SubmitEvent) {
|
||||||
|
e.preventDefault();
|
||||||
|
if (!this.org) return;
|
||||||
|
const { orgName } = serialize(e.target as HTMLFormElement);
|
||||||
|
|
||||||
|
this.isSavingOrgName = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await this.apiFetch(`/orgs/${this.org.id}/rename`, this.authState!, {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify({ name: orgName }),
|
||||||
|
});
|
||||||
|
|
||||||
|
this.notify({
|
||||||
|
message: msg("Updated organization name."),
|
||||||
|
variant: "success",
|
||||||
|
icon: "check2-circle",
|
||||||
|
duration: 8000,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.org = {
|
||||||
|
...this.org,
|
||||||
|
name: orgName as string,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.isEditingOrgName = false;
|
||||||
|
this.dispatchEvent(new CustomEvent("update-user-info"));
|
||||||
|
} catch (e) {
|
||||||
|
console.debug(e);
|
||||||
|
this.notify({
|
||||||
|
message: msg("Sorry, couldn't update organization name at this time."),
|
||||||
|
variant: "danger",
|
||||||
|
icon: "exclamation-octagon",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isSavingOrgName = false;
|
||||||
|
}
|
||||||
|
|
||||||
onInviteSuccess(
|
onInviteSuccess(
|
||||||
event: CustomEvent<{ inviteEmail: string; isExistingUser: boolean }>
|
event: CustomEvent<{ inviteEmail: string; isExistingUser: boolean }>
|
||||||
) {
|
) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user