- Introduced new `RadarConfig` structure in `config.go` to manage radar settings, including `statuses_url`, `http_timeout_ms`, and `ping_from`. - Implemented validation for radar configuration in `config_test.go` to ensure correct URL schemes and timeout limits. - Added new API routes for radar statuses and ping functionality in the gateway, enhancing the service's capabilities. - Updated documentation in `GATEWAY_RUN.md` to include details about the new radar features and their usage. - Enhanced the user interface to include navigation and display options for the Radar DC section in the sidebar and page titles. - Added client-side API functions for fetching radar statuses and ping responses, improving integration with the frontend.
242 lines
8.1 KiB
Svelte
242 lines
8.1 KiB
Svelte
<script lang="ts">
|
|
import { page } from '$app/state';
|
|
import LayoutDashboardIcon from '@lucide/svelte/icons/layout-dashboard';
|
|
import UsersIcon from '@lucide/svelte/icons/users';
|
|
import GlobeIcon from '@lucide/svelte/icons/globe';
|
|
import ServerIcon from '@lucide/svelte/icons/server';
|
|
import ActivityIcon from '@lucide/svelte/icons/activity';
|
|
import ShieldIcon from '@lucide/svelte/icons/shield';
|
|
import NetworkIcon from '@lucide/svelte/icons/network';
|
|
import SettingsIcon from '@lucide/svelte/icons/settings';
|
|
import RefreshCwIcon from '@lucide/svelte/icons/refresh-cw';
|
|
import ZapIcon from '@lucide/svelte/icons/zap';
|
|
import SirenIcon from '@lucide/svelte/icons/siren';
|
|
import RadioIcon from '@lucide/svelte/icons/radio';
|
|
import RadarIcon from '@lucide/svelte/icons/radar';
|
|
import * as Sidebar from '$lib/components/ui/sidebar/index.js';
|
|
|
|
let {
|
|
serverAliases = [] as string[],
|
|
serverPath = '' as string
|
|
}: {
|
|
serverAliases?: string[];
|
|
serverPath?: string;
|
|
} = $props();
|
|
|
|
function active(href: string): boolean {
|
|
const p = page.url.pathname;
|
|
if (href === '/') return p === '/';
|
|
return p === href || p.startsWith(href + '/');
|
|
}
|
|
|
|
/** Только точное совпадение (для корня ноды `/servers/{alias}` — иначе вложенные страницы вроде …/mihomo подсвечивали бы и Dashboard). */
|
|
function activeExact(href: string): boolean {
|
|
return page.url.pathname === href;
|
|
}
|
|
</script>
|
|
|
|
<Sidebar.Root collapsible="icon">
|
|
<Sidebar.Header>
|
|
<Sidebar.Menu>
|
|
<Sidebar.MenuItem>
|
|
<Sidebar.MenuButton size="lg" class="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground">
|
|
<div class="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
|
|
<ServerIcon class="size-4" />
|
|
</div>
|
|
<div class="grid flex-1 text-left text-sm leading-tight">
|
|
<span class="truncate font-semibold">Telemt Panel</span>
|
|
<span class="truncate text-xs text-muted-foreground">мультисервер</span>
|
|
</div>
|
|
</Sidebar.MenuButton>
|
|
</Sidebar.MenuItem>
|
|
</Sidebar.Menu>
|
|
</Sidebar.Header>
|
|
<Sidebar.Content>
|
|
<Sidebar.Group>
|
|
<Sidebar.GroupLabel>Флот</Sidebar.GroupLabel>
|
|
<Sidebar.Menu>
|
|
<Sidebar.MenuItem>
|
|
<Sidebar.MenuButton isActive={active('/')} tooltipContent="Обзор">
|
|
{#snippet child({ props })}
|
|
<a href="/" {...props}>
|
|
<LayoutDashboardIcon />
|
|
<span>Обзор</span>
|
|
</a>
|
|
{/snippet}
|
|
</Sidebar.MenuButton>
|
|
</Sidebar.MenuItem>
|
|
<Sidebar.MenuItem>
|
|
<Sidebar.MenuButton isActive={active('/users')} tooltipContent="Пользователи">
|
|
{#snippet child({ props })}
|
|
<a href="/users" {...props}>
|
|
<UsersIcon />
|
|
<span>Пользователи</span>
|
|
</a>
|
|
{/snippet}
|
|
</Sidebar.MenuButton>
|
|
</Sidebar.MenuItem>
|
|
<Sidebar.MenuItem>
|
|
<Sidebar.MenuButton isActive={active('/ips')} tooltipContent="IP">
|
|
{#snippet child({ props })}
|
|
<a href="/ips" {...props}>
|
|
<GlobeIcon />
|
|
<span>Уникальные IP</span>
|
|
</a>
|
|
{/snippet}
|
|
</Sidebar.MenuButton>
|
|
</Sidebar.MenuItem>
|
|
<Sidebar.MenuItem>
|
|
<Sidebar.MenuButton isActive={active('/incidents')} tooltipContent="Инциденты">
|
|
{#snippet child({ props })}
|
|
<a href="/incidents" {...props}>
|
|
<SirenIcon />
|
|
<span>Инциденты</span>
|
|
</a>
|
|
{/snippet}
|
|
</Sidebar.MenuButton>
|
|
</Sidebar.MenuItem>
|
|
<Sidebar.MenuItem>
|
|
<Sidebar.MenuButton isActive={active('/live')} tooltipContent="Live">
|
|
{#snippet child({ props })}
|
|
<a href="/live" {...props}>
|
|
<RadioIcon />
|
|
<span>Live</span>
|
|
</a>
|
|
{/snippet}
|
|
</Sidebar.MenuButton>
|
|
</Sidebar.MenuItem>
|
|
<Sidebar.MenuItem>
|
|
<Sidebar.MenuButton isActive={active('/radar')} tooltipContent="Радар DC Telegram">
|
|
{#snippet child({ props })}
|
|
<a href="/radar" {...props}>
|
|
<RadarIcon />
|
|
<span>Радар DC</span>
|
|
</a>
|
|
{/snippet}
|
|
</Sidebar.MenuButton>
|
|
</Sidebar.MenuItem>
|
|
<Sidebar.MenuItem>
|
|
<Sidebar.MenuButton isActive={active('/mihomo')} tooltipContent="Mihomo (флот)">
|
|
{#snippet child({ props })}
|
|
<a href="/mihomo" {...props}>
|
|
<ZapIcon />
|
|
<span>Mihomo</span>
|
|
</a>
|
|
{/snippet}
|
|
</Sidebar.MenuButton>
|
|
</Sidebar.MenuItem>
|
|
</Sidebar.Menu>
|
|
</Sidebar.Group>
|
|
{#if serverAliases.length > 0}
|
|
<Sidebar.Group>
|
|
<Sidebar.GroupLabel>Серверы</Sidebar.GroupLabel>
|
|
<Sidebar.Menu>
|
|
{#each serverAliases as a (a)}
|
|
<Sidebar.MenuItem>
|
|
<Sidebar.MenuButton
|
|
isActive={serverPath.startsWith('/servers/' + a)}
|
|
tooltipContent={a}
|
|
>
|
|
{#snippet child({ props })}
|
|
<a href="/servers/{encodeURIComponent(a)}" {...props}>
|
|
<ServerIcon />
|
|
<span>{a}</span>
|
|
</a>
|
|
{/snippet}
|
|
</Sidebar.MenuButton>
|
|
</Sidebar.MenuItem>
|
|
{/each}
|
|
</Sidebar.Menu>
|
|
</Sidebar.Group>
|
|
{/if}
|
|
{#if serverPath}
|
|
<Sidebar.Group>
|
|
<Sidebar.GroupLabel>Нода</Sidebar.GroupLabel>
|
|
<Sidebar.Menu>
|
|
<Sidebar.MenuItem>
|
|
<Sidebar.MenuButton isActive={activeExact(serverPath)} tooltipContent="Обзор">
|
|
{#snippet child({ props })}
|
|
<a href={serverPath} {...props}>
|
|
<LayoutDashboardIcon />
|
|
<span>Обзор</span>
|
|
</a>
|
|
{/snippet}
|
|
</Sidebar.MenuButton>
|
|
</Sidebar.MenuItem>
|
|
<Sidebar.MenuItem>
|
|
<Sidebar.MenuButton isActive={active(serverPath + '/mihomo')} tooltipContent="Mihomo">
|
|
{#snippet child({ props })}
|
|
<a href="{serverPath}/mihomo" {...props}>
|
|
<ZapIcon />
|
|
<span>Mihomo</span>
|
|
</a>
|
|
{/snippet}
|
|
</Sidebar.MenuButton>
|
|
</Sidebar.MenuItem>
|
|
<Sidebar.MenuItem>
|
|
<Sidebar.MenuButton isActive={active(serverPath + '/runtime')} tooltipContent="Состояние">
|
|
{#snippet child({ props })}
|
|
<a href="{serverPath}/runtime" {...props}>
|
|
<ActivityIcon />
|
|
<span>Состояние</span>
|
|
</a>
|
|
{/snippet}
|
|
</Sidebar.MenuButton>
|
|
</Sidebar.MenuItem>
|
|
<Sidebar.MenuItem>
|
|
<Sidebar.MenuButton isActive={active(serverPath + '/users')} tooltipContent="Пользователи">
|
|
{#snippet child({ props })}
|
|
<a href="{serverPath}/users" {...props}>
|
|
<UsersIcon />
|
|
<span>Пользователи</span>
|
|
</a>
|
|
{/snippet}
|
|
</Sidebar.MenuButton>
|
|
</Sidebar.MenuItem>
|
|
<Sidebar.MenuItem>
|
|
<Sidebar.MenuButton isActive={active(serverPath + '/security')} tooltipContent="Безопасность">
|
|
{#snippet child({ props })}
|
|
<a href="{serverPath}/security" {...props}>
|
|
<ShieldIcon />
|
|
<span>Безопасность</span>
|
|
</a>
|
|
{/snippet}
|
|
</Sidebar.MenuButton>
|
|
</Sidebar.MenuItem>
|
|
<Sidebar.MenuItem>
|
|
<Sidebar.MenuButton isActive={active(serverPath + '/upstreams')} tooltipContent="Апстримы и ДЦ">
|
|
{#snippet child({ props })}
|
|
<a href="{serverPath}/upstreams" {...props}>
|
|
<NetworkIcon />
|
|
<span>Апстримы и ДЦ</span>
|
|
</a>
|
|
{/snippet}
|
|
</Sidebar.MenuButton>
|
|
</Sidebar.MenuItem>
|
|
<Sidebar.MenuItem>
|
|
<Sidebar.MenuButton isActive={active(serverPath + '/config')} tooltipContent="Конфигурация">
|
|
{#snippet child({ props })}
|
|
<a href="{serverPath}/config" {...props}>
|
|
<SettingsIcon />
|
|
<span>Конфигурация</span>
|
|
</a>
|
|
{/snippet}
|
|
</Sidebar.MenuButton>
|
|
</Sidebar.MenuItem>
|
|
<Sidebar.MenuItem>
|
|
<Sidebar.MenuButton isActive={active(serverPath + '/update')} tooltipContent="Обновление">
|
|
{#snippet child({ props })}
|
|
<a href="{serverPath}/update" {...props}>
|
|
<RefreshCwIcon />
|
|
<span>Обновление</span>
|
|
</a>
|
|
{/snippet}
|
|
</Sidebar.MenuButton>
|
|
</Sidebar.MenuItem>
|
|
</Sidebar.Menu>
|
|
</Sidebar.Group>
|
|
{/if}
|
|
</Sidebar.Content>
|
|
<Sidebar.Rail />
|
|
</Sidebar.Root>
|