feat(builder-parity): enrich inspector summary and internal dashboard list columns

This commit is contained in:
Ashwin Kumar 2026-03-19 21:11:59 +01:00
parent 12396a81c5
commit 5140d12332
2 changed files with 97 additions and 12 deletions

View file

@ -311,6 +311,7 @@ export default function InternalDashboardManagementPage() {
<thead>
<tr>
<th>Role</th>
<th>Role ID</th>
<th>Dashboard</th>
<th>Status</th>
<th>Version</th>
@ -319,15 +320,16 @@ export default function InternalDashboardManagementPage() {
</thead>
<tbody>
<Show when={loading()}>
<tr><td colspan="5" style="text-align:center;padding:32px;color:#64748b">Loading internal dashboards...</td></tr>
<tr><td colspan="6" style="text-align:center;padding:32px;color:#64748b">Loading internal dashboards...</td></tr>
</Show>
<Show when={!loading() && dashboards().length === 0}>
<tr><td colspan="5" style="text-align:center;padding:32px;color:#94a3b8">No internal dashboards found. Create the first one.</td></tr>
<tr><td colspan="6" style="text-align:center;padding:32px;color:#94a3b8">No internal dashboards found. Create the first one.</td></tr>
</Show>
<For each={dashboards()}>
{(d) => (
<tr>
<td style="color:#475569">{d.roleName || 'Not linked'}</td>
<td style="color:#475569">{d.roleId || 'Not linked'}</td>
<td style="font-weight:600;color:#0f172a">{d.title}</td>
<td><span class={`status-chip ${d.status === 'published' ? 'active' : ''}`}>{d.status}</span></td>
<td style="color:#64748b">v{d.version}</td>

View file

@ -10,10 +10,15 @@ type ExternalRole = {
roleKey: string;
displayName: string;
vertical: string;
roleCategory: string;
onboardingSchemaId: string;
runtimeConfigVersion: number;
enabledModules: string[];
permissions: Record<string, string[]>;
featureLimits: Record<string, unknown>;
requiresOnboardingApproval: boolean;
requiresLeadApproval: boolean;
requiresJobApproval: boolean;
isActive: boolean;
};
@ -24,10 +29,15 @@ function parseRole(item: any): ExternalRole {
roleKey: String(cfg.roleKey || item.key || item.role_key || ''),
displayName: String(cfg.displayName || item.name || ''),
vertical: String(cfg.vertical || ''),
roleCategory: String(cfg.roleCategory || ''),
onboardingSchemaId: String(cfg.onboardingSchemaId || ''),
runtimeConfigVersion: Number(cfg.version || cfg.runtimeConfigVersion || 1),
enabledModules: Array.isArray(cfg.enabledModules) ? cfg.enabledModules : [],
permissions: (cfg.permissions && typeof cfg.permissions === 'object') ? cfg.permissions : {},
featureLimits: (cfg.featureLimits && typeof cfg.featureLimits === 'object') ? cfg.featureLimits : {},
requiresOnboardingApproval: cfg.requiresOnboardingApproval ?? false,
requiresLeadApproval: cfg.requiresLeadApproval ?? false,
requiresJobApproval: cfg.requiresJobApproval ?? false,
isActive: item.is_active !== false,
};
}
@ -52,6 +62,17 @@ export default function RoleUiConfigsViewPage() {
const roleKey = createMemo(() => searchParams.roleKey || '');
const [rows] = createResource(loadRoles);
const [selected] = createResource(roleKey, async (key) => (key ? loadRoleByKey(key) : null));
const permissionActions = ['read', 'create', 'update', 'delete', 'approve'];
const approvalFlags = createMemo(() => {
const value = selected();
if (!value) return [] as string[];
const flags: string[] = [];
if (value.requiresOnboardingApproval) flags.push('Onboarding Approval');
if (value.requiresLeadApproval) flags.push('Lead Approval');
if (value.requiresJobApproval) flags.push('Job Approval');
return flags;
});
return (
<AdminShell>
@ -125,16 +146,78 @@ export default function RoleUiConfigsViewPage() {
<div class="card"><p class="notice">Select an external role to view its current dashboard configuration.</p></div>
</Show>
<Show when={selected()}>
<div class="card">
<div class="field-grid-2">
<div class="kv-item"><p class="kv-label">Role Key</p><p class="kv-value">{selected()!.roleKey}</p></div>
<div class="kv-item"><p class="kv-label">Display Name</p><p class="kv-value">{selected()!.displayName}</p></div>
<div class="kv-item"><p class="kv-label">Vertical</p><p class="kv-value">{selected()!.vertical || '—'}</p></div>
<div class="kv-item"><p class="kv-label">Schema</p><p class="kv-value">{selected()!.onboardingSchemaId || '—'}</p></div>
<div class="kv-item" style="grid-column:1 / -1"><p class="kv-label">Enabled Modules</p><p class="kv-value">{selected()!.enabledModules.join(', ') || '—'}</p></div>
</div>
<h2 style="margin:14px 0 8px">Published Runtime Config</h2>
<pre class="json">{JSON.stringify(selected(), null, 2)}</pre>
<div style="display:flex;flex-direction:column;gap:12px">
<section class="card">
<div class="field-grid-2">
<div class="kv-item"><p class="kv-label">Role Key</p><p class="kv-value">{selected()!.roleKey}</p></div>
<div class="kv-item"><p class="kv-label">Display Name</p><p class="kv-value">{selected()!.displayName}</p></div>
<div class="kv-item"><p class="kv-label">Vertical</p><p class="kv-value">{selected()!.vertical || '—'}</p></div>
<div class="kv-item">
<p class="kv-label">Status</p>
<p class="kv-value">
<span class={`status-pill ${selected()!.isActive ? 'status-approved' : 'status-rejected'}`}>{selected()!.isActive ? 'Active' : 'Inactive'}</span>
</p>
</div>
<div class="kv-item"><p class="kv-label">Role Category</p><p class="kv-value">{selected()!.roleCategory || '—'}</p></div>
<div class="kv-item"><p class="kv-label">Onboarding Schema</p><p class="kv-value">{selected()!.onboardingSchemaId || '—'}</p></div>
<div class="kv-item"><p class="kv-label">Runtime Config Version</p><p class="kv-value">{selected()!.runtimeConfigVersion}</p></div>
<div class="kv-item">
<p class="kv-label">Approval Flags</p>
<p class="kv-value">
<Show when={approvalFlags().length > 0} fallback={'None'}>
<span style="display:inline-flex;gap:6px;flex-wrap:wrap">
{approvalFlags().map((flag) => <span class="status-pill status-pending">{flag}</span>)}
</span>
</Show>
</p>
</div>
</div>
</section>
<section class="card">
<h2 style="margin:0 0 8px">Enabled Modules</h2>
<Show when={selected()!.enabledModules.length > 0} fallback={<p class="notice">No modules configured.</p>}>
<div style="display:flex;flex-wrap:wrap;gap:8px">
{selected()!.enabledModules.map((moduleKey) => <span class="meta-chip">{moduleKey}</span>)}
</div>
</Show>
</section>
<section class="card">
<h2 style="margin:0 0 8px">Permission Matrix</h2>
<div class="table-wrap">
<table class="list-table">
<thead>
<tr>
<th>Module</th>
{permissionActions.map((action) => <th class="align-right">{action}</th>)}
</tr>
</thead>
<tbody>
{selected()!.enabledModules.map((moduleKey) => (
<tr>
<td>{moduleKey}</td>
{permissionActions.map((action) => (
<td class="align-right">
<input type="checkbox" checked={(selected()!.permissions[moduleKey] || []).includes(action)} disabled />
</td>
))}
</tr>
))}
</tbody>
</table>
</div>
</section>
<section class="card">
<h2 style="margin:0 0 8px">Feature Limits</h2>
<pre class="json">{JSON.stringify(selected()!.featureLimits || {}, null, 2)}</pre>
</section>
<section class="card">
<h2 style="margin:0 0 8px">Published Runtime Config</h2>
<pre class="json">{JSON.stringify(selected(), null, 2)}</pre>
</section>
</div>
</Show>
</section>