feat(app): wire dashboard administration flows

This commit is contained in:
2026-05-07 15:35:37 +00:00
parent e9eb9b4172
commit 91f06ccae1
91 changed files with 4087 additions and 5863 deletions
+40 -36
View File
@@ -58,7 +58,7 @@ export class LeleAccountNavigation extends DeesElement {
description,
});
if (result) {
await this.navigateTo(result.path.replace('/account', ''));
await this.navigateTo(result.path.replace('/dash', ''));
}
}
}
@@ -101,8 +101,7 @@ export class LeleAccountNavigation extends DeesElement {
opacity: 0.8;
}
.logo dees-icon {
font-size: 24px;
.logo idp-icon {
opacity: 0.9;
}
@@ -157,13 +156,12 @@ export class LeleAccountNavigation extends DeesElement {
color: var(--foreground);
}
.navigationOption dees-icon {
font-size: 16px;
.navigationOption idp-icon {
opacity: 0.7;
flex-shrink: 0;
}
.navigationOption:hover dees-icon {
.navigationOption:hover idp-icon {
opacity: 1;
}
@@ -172,7 +170,7 @@ export class LeleAccountNavigation extends DeesElement {
color: var(--foreground);
}
.navigationOption.active dees-icon {
.navigationOption.active idp-icon {
opacity: 1;
}
@@ -182,7 +180,7 @@ export class LeleAccountNavigation extends DeesElement {
margin: 8px 16px;
}
dees-input-dropdown {
idp-select {
margin: 8px;
}
`,
@@ -197,7 +195,7 @@ export class LeleAccountNavigation extends DeesElement {
return html`
<div class="logoArea">
<div class="logo">
<dees-icon .icon=${'lucide:fingerprint'}></dees-icon>
<idp-icon name="fingerprint" size="22"></idp-icon>
idp.global
</div>
</div>
@@ -208,7 +206,7 @@ export class LeleAccountNavigation extends DeesElement {
class="navigationOption ${this.isActive('') ? 'active' : ''}"
@click=${() => this.navigateTo('')}
>
<dees-icon .icon=${'lucide:home'}></dees-icon>
<idp-icon name="home" size="16"></idp-icon>
Overview
</div>
<div
@@ -217,7 +215,7 @@ export class LeleAccountNavigation extends DeesElement {
}}
>
<dees-icon .icon=${'lucide:shield'}></dees-icon>
<idp-icon name="shield" size="16"></idp-icon>
Manage Roles
</div>
<div
@@ -227,21 +225,21 @@ export class LeleAccountNavigation extends DeesElement {
idpState.domtools.router.pushUrl('/logout');
}}
>
<dees-icon .icon=${'lucide:power'}></dees-icon>
<idp-icon name="power" size="16"></idp-icon>
Log Out
</div>
<div class="divider"></div>
<div class="navigationGroupLabel">Organization</div>
<dees-input-dropdown
.label=${'Select organization'}
@selectedOption=${async (eventArg: CustomEvent) => {
<idp-select
label="Select organization"
@idp-select=${async (eventArg: CustomEvent<plugins.idpCatalog.IIdpSelectEventDetail>) => {
// Handle "Create new..." option
if (eventArg.detail.key === '__create_new__') {
const org = await CreateOrgModal.show();
if (org) {
await this.navigateTo(`/org/${org.data.slug}/billing`);
await this.navigateTo(`/org/${org.data.slug}/settings`);
}
return;
}
@@ -252,9 +250,9 @@ export class LeleAccountNavigation extends DeesElement {
// Auto-navigate to new org's current page type (reactivity)
const currentPath = window.location.pathname;
if (currentPath.includes('/org/') && newOrg) {
// Extract the page type (apps, billing, etc.) and navigate to new org
// Extract the page type (apps, settings, etc.) and navigate to new org
const pathParts = currentPath.split('/');
const pageType = pathParts[5]; // /account/org/:orgName/:pageType
const pageType = pathParts[4]; // /dash/org/:orgName/:pageType
if (pageType) {
await this.navigateTo(`/org/${newOrg.data.slug}/${pageType}`);
} else {
@@ -262,42 +260,42 @@ export class LeleAccountNavigation extends DeesElement {
}
}
}}
></dees-input-dropdown>
></idp-select>
<div
class="navigationOption ${this.isActive('org-overview') ? 'active' : ''}"
@click=${() => this.navigateToOrgPage('')}
>
<dees-icon .icon=${'lucide:home'}></dees-icon>
<idp-icon name="home" size="16"></idp-icon>
Overview
</div>
<div
class="navigationOption ${this.isActive('apps') ? 'active' : ''}"
@click=${() => this.navigateToOrgPage('apps')}
>
<dees-icon .icon=${'lucide:box'}></dees-icon>
<idp-icon name="box" size="16"></idp-icon>
Apps
</div>
<div
class="navigationOption ${this.isActive('users') ? 'active' : ''}"
@click=${() => this.navigateToOrgPage('users')}
>
<dees-icon .icon=${'lucide:users'}></dees-icon>
<idp-icon name="users" size="16"></idp-icon>
Users
</div>
<div
class="navigationOption"
@click=${async () => {}}
>
<dees-icon .icon=${'lucide:activity'}></dees-icon>
<idp-icon name="activity" size="16"></idp-icon>
Activity
</div>
<div
class="navigationOption ${this.isActive('billing') ? 'active' : ''}"
@click=${() => this.navigateToOrgPage('billing')}
class="navigationOption ${this.isActive('settings') ? 'active' : ''}"
@click=${() => this.navigateToOrgPage('settings')}
>
<dees-icon .icon=${'lucide:wallet'}></dees-icon>
Billing
<idp-icon name="settings" size="16"></idp-icon>
Settings
</div>
${this.renderAdminLink()}
@@ -318,7 +316,7 @@ export class LeleAccountNavigation extends DeesElement {
class="navigationOption ${this.isActive('admin') ? 'active' : ''}"
@click=${() => this.navigateTo('/admin')}
>
<dees-icon .icon=${'lucide:shield'}></dees-icon>
<idp-icon name="shield" size="16"></idp-icon>
Global Admin
</div>
`;
@@ -328,11 +326,11 @@ export class LeleAccountNavigation extends DeesElement {
const path = this.currentPath;
if (page === '') {
// Account overview - exact match
return path === '/account' || path === '/account/';
return path === '/dash' || path === '/dash/';
}
if (page === 'org-overview') {
// Org overview - /account/org/:slug without trailing page type
return /^\/account\/org\/[^\/]+\/?$/.test(path);
// Org overview - /dash/org/:slug without trailing page type
return /^\/dash\/org\/[^\/]+\/?$/.test(path);
}
// For other pages, check if the path contains the page segment
return path.includes(`/${page}`);
@@ -355,8 +353,8 @@ export class LeleAccountNavigation extends DeesElement {
};
requestAnimationFrame(checkPath);
const deesInputDropdown = this.shadowRoot.querySelector('dees-input-dropdown');
const orgToMenuEntry = (orgArg?: plugins.idpInterfaces.data.IOrganization) => {
const orgSelect = this.shadowRoot.querySelector('idp-select') as plugins.idpCatalog.IdpSelect | null;
const orgToMenuEntry = (orgArg?: plugins.idpInterfaces.data.IOrganization): plugins.idpCatalog.IIdpSelectOption | null => {
if (!orgArg) {
return null;
}
@@ -378,19 +376,25 @@ export class LeleAccountNavigation extends DeesElement {
.select((stateArg) => stateArg.organizations)
.pipe(
plugins.deesDomtools.plugins.smartrx.rxjs.ops.map((orgArrayArg) => {
const orgEntries = orgArrayArg.map(orgToMenuEntry);
const orgEntries = orgArrayArg
.map(orgToMenuEntry)
.filter((entryArg): entryArg is plugins.idpCatalog.IIdpSelectOption => Boolean(entryArg));
// Add "Create new..." at the end
return [...orgEntries, createNewOption];
})
)
.subscribe((menuEntries) => {
deesInputDropdown.options = menuEntries;
if (orgSelect) {
orgSelect.options = menuEntries;
}
});
states.accountState
.select((stateArg) => stateArg.selectedOrg)
.pipe(plugins.deesDomtools.plugins.smartrx.rxjs.ops.map(orgToMenuEntry))
.subscribe((selectedOrgArg) => {
deesInputDropdown.selectedOption = selectedOrgArg;
if (orgSelect) {
orgSelect.selectedOption = selectedOrgArg;
}
});
// Check if user is global admin