Refactor user table display logic in users page
Publish telemt-api gateway Docker image / test (push) Successful in 26s
Publish telemt-api gateway Docker image / build-and-push (push) Successful in 2m11s

- 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:
Denozordec
2026-03-30 13:48:40 +07:00
parent 40bcfbf993
commit 43ef4a799e
+80 -50
View File
@@ -127,58 +127,88 @@
{@const username = row.username ?? ''} {@const username = row.username ?? ''}
{@const pairs = ipServerPairsByUser[username] ?? []} {@const pairs = ipServerPairsByUser[username] ?? []}
<Table.Row> {#if pairs.length === 0}
<Table.Cell class="font-medium"> <Table.Row>
<a href="/users/{encodeURIComponent(row.username ?? '')}" class="text-primary hover:underline"> <Table.Cell class="font-medium">
{row.username} <a href="/users/{encodeURIComponent(row.username ?? '')}" class="text-primary hover:underline">
</a> {row.username}
</Table.Cell> </a>
<Table.Cell> </Table.Cell>
<div class="flex flex-wrap gap-1"> <Table.Cell>
{#each row.links?.tls ?? [] as link (link)} <div class="flex flex-wrap gap-1">
<Button variant="outline" size="xs" class="h-7 gap-1 px-2 text-xs" onclick={() => copy(link)}> {#each row.links?.tls ?? [] as link (link)}
TLS <Button variant="outline" size="xs" class="h-7 gap-1 px-2 text-xs" onclick={() => copy(link)}>
<CopyIcon class="size-3 opacity-60" /> TLS
</Button> <CopyIcon class="size-3 opacity-60" />
{/each} </Button>
{#each row.links?.secure ?? [] as link (link)} {/each}
<Button variant="outline" size="xs" class="h-7 gap-1 px-2 text-xs" onclick={() => copy(link)}> {#each row.links?.secure ?? [] as link (link)}
t.me <Button variant="outline" size="xs" class="h-7 gap-1 px-2 text-xs" onclick={() => copy(link)}>
<CopyIcon class="size-3 opacity-60" /> t.me
</Button> <CopyIcon class="size-3 opacity-60" />
{/each} </Button>
</div> {/each}
</Table.Cell> </div>
<Table.Cell class="text-right tabular-nums">{formatMiB(row.total_megabytes ?? 0)}</Table.Cell> </Table.Cell>
<Table.Cell class="text-right text-sm tabular-nums"> <Table.Cell class="text-right tabular-nums">{formatMiB(row.total_megabytes ?? 0)}</Table.Cell>
{#if (row.active_unique_ips ?? 0) > 0} <Table.Cell class="text-right text-sm font-mono"></Table.Cell>
{row.active_unique_ips} <Table.Cell class="text-right text-sm">
{#if row.max_unique_ips != null} {row.data_quota_bytes != null ? formatBytes(row.data_quota_bytes) : '—'}
<span class="text-muted-foreground"> / {row.max_unique_ips}</span> </Table.Cell>
{/if} <Table.Cell class="text-sm text-muted-foreground">
{:else} {row.expiration_rfc3339 ? new Date(row.expiration_rfc3339).toLocaleString() : '—'}
</Table.Cell>
{/if} </Table.Row>
</Table.Cell> {:else}
<Table.Cell class="text-right text-sm"> {#each pairs as pair, idx (pair.ip + '|' + pair.server)}
{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)}
<Table.Row> <Table.Row>
<Table.Cell>&nbsp;</Table.Cell> <Table.Cell class="font-medium">
<Table.Cell>&nbsp;</Table.Cell> <a href="/users/{encodeURIComponent(row.username ?? '')}" class="text-primary hover:underline">
<Table.Cell>&nbsp;</Table.Cell> {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}
&nbsp;
{/if}
</Table.Cell>
<Table.Cell class="text-right tabular-nums">
{#if idx === 0}
{formatMiB(row.total_megabytes ?? 0)}
{:else}
&nbsp;
{/if}
</Table.Cell>
<Table.Cell class="text-right text-sm font-mono">{pair.ip} - {pair.server}</Table.Cell> <Table.Cell class="text-right text-sm font-mono">{pair.ip} - {pair.server}</Table.Cell>
<Table.Cell>&nbsp;</Table.Cell> <Table.Cell class="text-right text-sm tabular-nums">
<Table.Cell>&nbsp;</Table.Cell> {#if idx === 0}
{row.data_quota_bytes != null ? formatBytes(row.data_quota_bytes) : '—'}
{:else}
&nbsp;
{/if}
</Table.Cell>
<Table.Cell class="text-sm text-muted-foreground">
{#if idx === 0}
{row.expiration_rfc3339 ? new Date(row.expiration_rfc3339).toLocaleString() : '—'}
{:else}
&nbsp;
{/if}
</Table.Cell>
</Table.Row> </Table.Row>
{/each} {/each}
{/if} {/if}