Refactor user table display logic in users page
- Updated the user table to conditionally render rows based on the presence of IP-server pairs, improving clarity in data presentation. - Simplified the rendering of user data when no pairs are available, ensuring a cleaner UI. - Enhanced the display of user links and metrics, maintaining consistent formatting across different scenarios.
This commit is contained in:
@@ -127,58 +127,88 @@
|
||||
{@const username = row.username ?? ''}
|
||||
{@const pairs = ipServerPairsByUser[username] ?? []}
|
||||
|
||||
<Table.Row>
|
||||
<Table.Cell class="font-medium">
|
||||
<a href="/users/{encodeURIComponent(row.username ?? '')}" class="text-primary hover:underline">
|
||||
{row.username}
|
||||
</a>
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<div class="flex flex-wrap gap-1">
|
||||
{#each row.links?.tls ?? [] as link (link)}
|
||||
<Button variant="outline" size="xs" class="h-7 gap-1 px-2 text-xs" onclick={() => copy(link)}>
|
||||
TLS
|
||||
<CopyIcon class="size-3 opacity-60" />
|
||||
</Button>
|
||||
{/each}
|
||||
{#each row.links?.secure ?? [] as link (link)}
|
||||
<Button variant="outline" size="xs" class="h-7 gap-1 px-2 text-xs" onclick={() => copy(link)}>
|
||||
t.me
|
||||
<CopyIcon class="size-3 opacity-60" />
|
||||
</Button>
|
||||
{/each}
|
||||
</div>
|
||||
</Table.Cell>
|
||||
<Table.Cell class="text-right tabular-nums">{formatMiB(row.total_megabytes ?? 0)}</Table.Cell>
|
||||
<Table.Cell class="text-right text-sm tabular-nums">
|
||||
{#if (row.active_unique_ips ?? 0) > 0}
|
||||
{row.active_unique_ips}
|
||||
{#if row.max_unique_ips != null}
|
||||
<span class="text-muted-foreground"> / {row.max_unique_ips}</span>
|
||||
{/if}
|
||||
{:else}
|
||||
—
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
<Table.Cell class="text-right text-sm">
|
||||
{row.data_quota_bytes != null ? formatBytes(row.data_quota_bytes) : '—'}
|
||||
</Table.Cell>
|
||||
<Table.Cell class="text-sm text-muted-foreground">
|
||||
{row.expiration_rfc3339
|
||||
? new Date(row.expiration_rfc3339).toLocaleString()
|
||||
: '—'}
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
|
||||
{#if pairs.length > 0}
|
||||
{#each pairs as pair (pair.ip + '|' + pair.server)}
|
||||
{#if pairs.length === 0}
|
||||
<Table.Row>
|
||||
<Table.Cell class="font-medium">
|
||||
<a href="/users/{encodeURIComponent(row.username ?? '')}" class="text-primary hover:underline">
|
||||
{row.username}
|
||||
</a>
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<div class="flex flex-wrap gap-1">
|
||||
{#each row.links?.tls ?? [] as link (link)}
|
||||
<Button variant="outline" size="xs" class="h-7 gap-1 px-2 text-xs" onclick={() => copy(link)}>
|
||||
TLS
|
||||
<CopyIcon class="size-3 opacity-60" />
|
||||
</Button>
|
||||
{/each}
|
||||
{#each row.links?.secure ?? [] as link (link)}
|
||||
<Button variant="outline" size="xs" class="h-7 gap-1 px-2 text-xs" onclick={() => copy(link)}>
|
||||
t.me
|
||||
<CopyIcon class="size-3 opacity-60" />
|
||||
</Button>
|
||||
{/each}
|
||||
</div>
|
||||
</Table.Cell>
|
||||
<Table.Cell class="text-right tabular-nums">{formatMiB(row.total_megabytes ?? 0)}</Table.Cell>
|
||||
<Table.Cell class="text-right text-sm font-mono">—</Table.Cell>
|
||||
<Table.Cell class="text-right text-sm">
|
||||
{row.data_quota_bytes != null ? formatBytes(row.data_quota_bytes) : '—'}
|
||||
</Table.Cell>
|
||||
<Table.Cell class="text-sm text-muted-foreground">
|
||||
{row.expiration_rfc3339 ? new Date(row.expiration_rfc3339).toLocaleString() : '—'}
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
{:else}
|
||||
{#each pairs as pair, idx (pair.ip + '|' + pair.server)}
|
||||
<Table.Row>
|
||||
<Table.Cell> </Table.Cell>
|
||||
<Table.Cell> </Table.Cell>
|
||||
<Table.Cell> </Table.Cell>
|
||||
<Table.Cell class="font-medium">
|
||||
<a href="/users/{encodeURIComponent(row.username ?? '')}" class="text-primary hover:underline">
|
||||
{row.username}
|
||||
</a>
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
{#if idx === 0}
|
||||
<div class="flex flex-wrap gap-1">
|
||||
{#each row.links?.tls ?? [] as link (link)}
|
||||
<Button variant="outline" size="xs" class="h-7 gap-1 px-2 text-xs" onclick={() => copy(link)}>
|
||||
TLS
|
||||
<CopyIcon class="size-3 opacity-60" />
|
||||
</Button>
|
||||
{/each}
|
||||
{#each row.links?.secure ?? [] as link (link)}
|
||||
<Button variant="outline" size="xs" class="h-7 gap-1 px-2 text-xs" onclick={() => copy(link)}>
|
||||
t.me
|
||||
<CopyIcon class="size-3 opacity-60" />
|
||||
</Button>
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
<Table.Cell class="text-right tabular-nums">
|
||||
{#if idx === 0}
|
||||
{formatMiB(row.total_megabytes ?? 0)}
|
||||
{:else}
|
||||
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
<Table.Cell class="text-right text-sm font-mono">{pair.ip} - {pair.server}</Table.Cell>
|
||||
<Table.Cell> </Table.Cell>
|
||||
<Table.Cell> </Table.Cell>
|
||||
<Table.Cell class="text-right text-sm tabular-nums">
|
||||
{#if idx === 0}
|
||||
{row.data_quota_bytes != null ? formatBytes(row.data_quota_bytes) : '—'}
|
||||
{:else}
|
||||
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
<Table.Cell class="text-sm text-muted-foreground">
|
||||
{#if idx === 0}
|
||||
{row.expiration_rfc3339 ? new Date(row.expiration_rfc3339).toLocaleString() : '—'}
|
||||
{:else}
|
||||
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
{/each}
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user