18 lines
2.9 KiB
Svelte
18 lines
2.9 KiB
Svelte
<script lang="ts">
|
|
import RegistryPagination from '$lib/components/RegistryPagination.svelte';
|
|
import KpiFilters from '$lib/components/KpiFilters.svelte';
|
|
import RoleBadgeList from '$lib/components/RoleBadgeList.svelte';
|
|
import SortableColumnHeader from '$lib/components/SortableColumnHeader.svelte';
|
|
let { data } = $props();
|
|
const date = (value: unknown) => value ? new Intl.DateTimeFormat(undefined, { dateStyle: 'medium', timeStyle: 'short' }).format(new Date(String(value))) : 'NEVER';
|
|
</script>
|
|
<svelte:head><title>User operations — ISAC</title></svelte:head>
|
|
<div class="module-toolbar"><div><p class="eyebrow">USER OPERATIONS</p><h2>AGENT REGISTRY</h2><p>Identity, authentication methods, access state, recent activity, and community contribution overview.</p></div></div>
|
|
<KpiFilters active={data.filter} items={[{value:'',label:'RESULTS',count:data.summary.results,description:'Show current query'},{value:'active',label:'ACTIVE',count:data.summary.active,description:'Active within 30 days'},{value:'inactive',label:'INACTIVE',count:data.summary.inactive,description:'No activity for 30 days'},{value:'restricted',label:'RESTRICTED',count:data.summary.restricted,description:'Blocked, banned, or deleted'}]}/>
|
|
<RegistryPagination pagination={data.pagination} search={data.query} searchPlaceholder="SEARCH DISPLAY OR LOGIN NAME"/>
|
|
<div class="dashboard-table">
|
|
<div class="dashboard-row user-row table-heading"><SortableColumnHeader label="USER" column="user" sort={data.sort}/><SortableColumnHeader label="ACCESS" column="access" sort={data.sort}/><SortableColumnHeader label="ROLES" column="roles" sort={data.sort}/><SortableColumnHeader label="LAST LOGIN" column="lastLogin" sort={data.sort} defaultDirection="desc"/><SortableColumnHeader label="LAST ACTIVE" column="lastActive" sort={data.sort} defaultDirection="desc"/><SortableColumnHeader label="CONTENT" column="content" sort={data.sort} defaultDirection="desc"/><span></span></div>
|
|
{#each data.users as user}<div class="dashboard-row user-row mobile-detail-row"><div><strong>{user.display_name}</strong><small>LOGIN: {user.username ?? 'NOT CONFIGURED'}</small></div><span class:restricted={user.accessState !== 'ACTIVE'}>{user.accessState}{user.inactive && user.accessState === 'ACTIVE' ? ' · INACTIVE' : ''}</span><RoleBadgeList roles={String(user.assigned_roles ?? user.role ?? 'User').split(' · ')} label={`Assigned roles for ${user.display_name}`} compact/><span><small>{user.last_login_provider?.toUpperCase() ?? 'NONE'}</small>{date(user.last_login_at)}</span><span>{date(user.last_active_at)}</span><span>{user.build_count} BUILDS · {user.comment_count} COMMENTS</span><a class="row-action" href={`/isac/users/${user.id}`}>VIEW</a><a class="mobile-row-open" href={`/isac/users/${user.id}`} aria-label={`View agent ${user.display_name}`}></a></div>
|
|
{:else}<div class="empty-dashboard"><strong>NO USERS FOUND</strong><span>Adjust the username search and try again.</span></div>{/each}
|
|
</div>
|