mirror of
https://github.com/pocket-id/pocket-id.git
synced 2025-12-17 10:43:04 +03:00
feat: add various improvements to the table component (#961)
Co-authored-by: Kyle Mendell <kmendell@ofkm.us>
This commit is contained in:
@@ -1,69 +1,111 @@
|
||||
<script lang="ts">
|
||||
import AdvancedTable from '$lib/components/advanced-table.svelte';
|
||||
import AdvancedTable from '$lib/components/table/advanced-table.svelte';
|
||||
import { Badge } from '$lib/components/ui/badge';
|
||||
import * as Table from '$lib/components/ui/table';
|
||||
import { m } from '$lib/paraglide/messages';
|
||||
import {translateAuditLogEvent} from "$lib/utils/audit-log-translator";
|
||||
import AuditLogService from '$lib/services/audit-log-service';
|
||||
import type { AuditLog } from '$lib/types/audit-log.type';
|
||||
import type { Paginated, SearchPaginationSortRequest } from '$lib/types/pagination.type';
|
||||
import type { AdvancedTableColumn } from '$lib/types/advanced-table.type';
|
||||
import type { AuditLog, AuditLogFilter } from '$lib/types/audit-log.type';
|
||||
import { translateAuditLogEvent } from '$lib/utils/audit-log-translator';
|
||||
|
||||
let {
|
||||
auditLogs,
|
||||
isAdmin = false,
|
||||
requestOptions
|
||||
filters
|
||||
}: {
|
||||
auditLogs: Paginated<AuditLog>;
|
||||
isAdmin?: boolean;
|
||||
requestOptions: SearchPaginationSortRequest;
|
||||
filters?: AuditLogFilter;
|
||||
} = $props();
|
||||
|
||||
const auditLogService = new AuditLogService();
|
||||
let tableRef: AdvancedTable<AuditLog>;
|
||||
|
||||
const columns: AdvancedTableColumn<AuditLog>[] = [
|
||||
{
|
||||
label: m.time(),
|
||||
column: 'createdAt',
|
||||
sortable: true,
|
||||
value: (item) => new Date(item.createdAt).toLocaleString()
|
||||
},
|
||||
{
|
||||
label: m.username(),
|
||||
column: 'username',
|
||||
hidden: !isAdmin,
|
||||
value: (item) => item.username ?? m.unknown()
|
||||
},
|
||||
{
|
||||
label: m.event(),
|
||||
column: 'event',
|
||||
sortable: true,
|
||||
cell: EventCell
|
||||
},
|
||||
{
|
||||
label: m.approximate_location(),
|
||||
key: 'location',
|
||||
value: (item) => formatLocation(item)
|
||||
},
|
||||
{
|
||||
label: m.ip_address(),
|
||||
column: 'ipAddress',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: m.device(),
|
||||
column: 'device',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: m.client(),
|
||||
key: 'client',
|
||||
value: (item) => item.data?.clientName
|
||||
}
|
||||
];
|
||||
|
||||
$effect(() => {
|
||||
if (filters) {
|
||||
tableRef?.refresh();
|
||||
}
|
||||
});
|
||||
|
||||
export async function refresh() {
|
||||
await tableRef.refresh();
|
||||
}
|
||||
|
||||
function formatLocation(log: AuditLog) {
|
||||
if (log.city && log.country) {
|
||||
return `${log.city}, ${log.country}`;
|
||||
} else if (log.country) {
|
||||
return log.country;
|
||||
} else {
|
||||
return m.unknown();
|
||||
}
|
||||
}
|
||||
|
||||
function wrapFilters(filters?: Record<string, string>) {
|
||||
if (!filters) return undefined;
|
||||
return Object.fromEntries(
|
||||
Object.entries(filters)
|
||||
.filter(([_, value]) => value !== undefined && value !== null && value !== '')
|
||||
.map(([key, value]) => [key, [value]])
|
||||
);
|
||||
}
|
||||
</script>
|
||||
|
||||
{#snippet EventCell({ item }: { item: AuditLog })}
|
||||
<Badge class="rounded-full" variant="outline">
|
||||
{translateAuditLogEvent(item.event)}
|
||||
</Badge>
|
||||
{/snippet}
|
||||
|
||||
<AdvancedTable
|
||||
items={auditLogs}
|
||||
{requestOptions}
|
||||
onRefresh={async (options) =>
|
||||
id="audit-log-list-{isAdmin ? 'admin' : 'user'}"
|
||||
bind:this={tableRef}
|
||||
fetchCallback={async (options) =>
|
||||
isAdmin
|
||||
? (auditLogs = await auditLogService.listAllLogs(options))
|
||||
: (auditLogs = await auditLogService.list(options))}
|
||||
columns={[
|
||||
{ label: m.time(), sortColumn: 'createdAt' },
|
||||
...(isAdmin ? [{ label: 'Username' }] : []),
|
||||
{ label: m.event(), sortColumn: 'event' },
|
||||
{ label: m.approximate_location(), sortColumn: 'city' },
|
||||
{ label: m.ip_address(), sortColumn: 'ipAddress' },
|
||||
{ label: m.device(), sortColumn: 'device' },
|
||||
{ label: m.client() }
|
||||
]}
|
||||
? await auditLogService.listAllLogs({
|
||||
...options,
|
||||
filters: wrapFilters(filters)
|
||||
})
|
||||
: await auditLogService.list(options)}
|
||||
defaultSort={{ column: 'createdAt', direction: 'desc' }}
|
||||
withoutSearch
|
||||
>
|
||||
{#snippet rows({ item })}
|
||||
<Table.Cell>{new Date(item.createdAt).toLocaleString()}</Table.Cell>
|
||||
{#if isAdmin}
|
||||
<Table.Cell>
|
||||
{#if item.username}
|
||||
{item.username}
|
||||
{:else}
|
||||
Unknown User
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{/if}
|
||||
<Table.Cell>
|
||||
<Badge class="rounded-full" variant="outline">{translateAuditLogEvent(item.event)}</Badge>
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
{#if item.city && item.country}
|
||||
{item.city}, {item.country}
|
||||
{:else if item.country}
|
||||
{item.country}
|
||||
{:else}
|
||||
{m.unknown()}
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
<Table.Cell>{item.ipAddress}</Table.Cell>
|
||||
<Table.Cell>{item.device}</Table.Cell>
|
||||
<Table.Cell>{item.data.clientName}</Table.Cell>
|
||||
{/snippet}
|
||||
</AdvancedTable>
|
||||
{columns}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user