From bc15d4e2cab8d4200890d5fa19182ab323761a23 Mon Sep 17 00:00:00 2001 From: Denozordec Date: Mon, 30 Mar 2026 14:27:16 +0700 Subject: [PATCH] Implement active IP server rows display in user traffic table - Introduced a new derived state to calculate and display active IP-server pairs for each user, enhancing the visibility of user connections. - Replaced the previous badge display with a structured table format, improving data organization and readability. - Updated the UI to conditionally render active connections, providing clearer feedback when no active connections are present. --- web/src/routes/+page.svelte | 109 +++++++++++++++++++++++++++++++----- 1 file changed, 95 insertions(+), 14 deletions(-) diff --git a/web/src/routes/+page.svelte b/web/src/routes/+page.svelte index a00234d..6da8674 100644 --- a/web/src/routes/+page.svelte +++ b/web/src/routes/+page.svelte @@ -205,9 +205,60 @@ function chipLabel(ip: components['schemas']['IPAssignments']): string { const cc = ip.country_code?.trim(); const flag = flagEmoji(cc ?? undefined); - const short = ip.ip && ip.ip.length > 12 ? ip.ip.slice(0, 8) + '…' : (ip.ip ?? ''); - return `${flag} ${cc ?? '?'} ${short}`.trim(); + const addr = ip.ip ?? ''; + return `${flag} ${cc ?? '?'} ${addr}`.trim(); } + + type ActiveIpServerRow = { + username: string; + ip: string; + country_code: string | null | undefined; + server: string; + activeLabel: string; + }; + + let activeIpServerRows = $derived.by((): ActiveIpServerRow[] => { + const out: ActiveIpServerRow[] = []; + const seen = new Set(); + const maxUniqueIpRows = 80; + const maxOutRows = 2000; + + for (const ur of uniqueIps?.slice(0, maxUniqueIpRows) ?? []) { + const username = ur.username ?? ''; + if (!username) continue; + + for (const ipa of ur.ips ?? []) { + const ip = ipa.ip ?? ''; + if (!ip) continue; + + const servers = ipa.active_on_servers ?? []; + if (servers.length === 0) continue; + + for (const server of servers) { + if (!server) continue; + const key = `${username}|${ip}|${server}`; + if (seen.has(key)) continue; + seen.add(key); + + out.push({ + username, + ip, + country_code: ipa.country_code, + server, + activeLabel: chipLabel(ipa) + }); + + if (out.length >= maxOutRows) return out; + } + } + } + + out.sort( + (a, b) => + a.ip.localeCompare(b.ip) || a.server.localeCompare(b.server) || a.username.localeCompare(b.username) + ); + return out; + });
@@ -387,18 +438,48 @@ С GeoIP при включённой базе на шлюзе -
- {#each (uniqueIps ?? []).slice(0, 80) as row (row.username)} - {#each row.ips ?? [] as ip (`${row.username ?? ''}-${ip.ip ?? ''}`)} - - {chipLabel(ip)} - - {/each} - {/each} - {#if (uniqueIps?.length ?? 0) === 0} - Нет данных - {/if} -
+ + + + IP со страной + Клиент + Сервер + + + + {#if (activeIpServerRows?.length ?? 0) === 0} + + + Нет активных подключений + + + {:else} + {#each activeIpServerRows as r (r.username + '|' + r.ip + '|' + r.server)} + + + {r.activeLabel} + + + + {r.username} + + + + + {r.server} + + + + {/each} + {/if} + +