Docker images / prepare-release (push) Successful in 9s
Docker images / backend-image (push) Successful in 1m40s
Docker images / frontend-image (push) Successful in 2m47s
Docker images / notify-webhook (push) Skipped
Docker images / updater-image (push) Successful in 38s
Docker images / publish-release (push) Successful in 8s
Updated CodeExportSheet to improve UI elements, including the addition of a Badge component for live status indication and refined layout adjustments. Modified WgExportSheet to simplify format labels and incorporate live content fetching capabilities. Adjusted styles for better visual consistency and user experience.
148 lines
4.0 KiB
TypeScript
148 lines
4.0 KiB
TypeScript
"use client"
|
||
|
||
import { useMemo } from "react"
|
||
import type { WgIfaceWithServer } from "@/components/data-grids/wireguard-data-grid"
|
||
import {
|
||
CodeExportSheet,
|
||
type CodeExportFormat,
|
||
} from "@/components/reui-kit/code-export-sheet"
|
||
import {
|
||
generateMikrotikRsc,
|
||
generateNativeConf,
|
||
generatePeerClientConf,
|
||
} from "@/lib/wg-config"
|
||
|
||
function WgExportSheet({
|
||
open,
|
||
iface,
|
||
onClose,
|
||
liveContent,
|
||
liveBusy,
|
||
onRequestLiveExport,
|
||
initialTab = "rsc",
|
||
peerId,
|
||
}: {
|
||
open: boolean
|
||
iface: WgIfaceWithServer | null
|
||
onClose: () => void
|
||
liveContent?: { rsc?: string; conf?: string; peerConf?: string } | null
|
||
liveBusy?: boolean
|
||
onRequestLiveExport?: (format: "rsc" | "conf" | "peer-conf") => void
|
||
initialTab?: "rsc" | "conf" | "peer"
|
||
/** Selected peer for Peer .conf (defaults to first peer) */
|
||
peerId?: string | null
|
||
}) {
|
||
const formats = useMemo((): CodeExportFormat[] => {
|
||
if (!iface) {
|
||
return [
|
||
{ id: "rsc", label: ".rsc", filename: "wg.rsc", code: "" },
|
||
{ id: "conf", label: ".conf", filename: "wg.conf", code: "" },
|
||
{
|
||
id: "peer",
|
||
label: "Peer",
|
||
filename: "wg-peer.conf",
|
||
code: "",
|
||
emptyMessage: "Интерфейс не выбран",
|
||
},
|
||
]
|
||
}
|
||
|
||
const base = {
|
||
name: iface.name,
|
||
listenPort: iface.listenPort,
|
||
mtu: iface.mtu,
|
||
comment: iface.comment,
|
||
enabled: iface.enabled,
|
||
privateKey: iface.privateKey,
|
||
publicKey: iface.publicKey,
|
||
address: iface.address,
|
||
serverName: iface.serverName,
|
||
peers: iface.peers.map((p) => ({
|
||
publicKey: p.publicKey,
|
||
allowedIps: p.allowedIps,
|
||
endpoint: p.endpoint,
|
||
persistentKeepalive: p.persistentKeepalive,
|
||
persistent: p.persistent,
|
||
comment: p.comment,
|
||
name: p.name,
|
||
clientAddress: p.clientAddress,
|
||
clientDns: p.clientDns,
|
||
clientEndpoint: p.clientEndpoint,
|
||
})),
|
||
}
|
||
|
||
const peer =
|
||
(peerId
|
||
? iface.peers.find((p) => p.id === peerId || p.rosId === peerId)
|
||
: undefined) ?? iface.peers[0]
|
||
|
||
const localRsc = generateMikrotikRsc(base)
|
||
const localConf = generateNativeConf(base)
|
||
|
||
let peerConf = ""
|
||
let peerEmpty: string | undefined
|
||
if (!iface.publicKey) {
|
||
peerEmpty = "Нет public-key интерфейса для клиентского .conf"
|
||
} else if (!peer) {
|
||
peerEmpty = "Нет пиров для экспорта Peer .conf"
|
||
} else {
|
||
peerConf = generatePeerClientConf({
|
||
peerAddress: peer.clientAddress,
|
||
peerDns: peer.clientDns,
|
||
serverPublicKey: iface.publicKey,
|
||
allowedIps: peer.allowedIps,
|
||
endpoint: peer.clientEndpoint || peer.endpoint || undefined,
|
||
persistentKeepalive: peer.persistentKeepalive ?? 25,
|
||
})
|
||
}
|
||
|
||
return [
|
||
{
|
||
id: "rsc",
|
||
label: ".rsc",
|
||
filename: `${iface.name}.rsc`,
|
||
code: liveContent?.rsc ?? localRsc,
|
||
isLive: Boolean(liveContent?.rsc),
|
||
},
|
||
{
|
||
id: "conf",
|
||
label: ".conf",
|
||
filename: `${iface.name}.conf`,
|
||
code: liveContent?.conf ?? localConf,
|
||
isLive: Boolean(liveContent?.conf),
|
||
},
|
||
{
|
||
id: "peer",
|
||
label: "Peer",
|
||
filename: `${iface.name}-peer.conf`,
|
||
code: liveContent?.peerConf ?? peerConf,
|
||
emptyMessage: liveContent?.peerConf ? undefined : peerEmpty,
|
||
isLive: Boolean(liveContent?.peerConf),
|
||
},
|
||
]
|
||
}, [iface, liveContent, peerId])
|
||
|
||
return (
|
||
<CodeExportSheet
|
||
open={open}
|
||
onClose={onClose}
|
||
title="Экспорт WireGuard"
|
||
description={iface ? `${iface.name} · ${iface.serverName}` : "—"}
|
||
formats={formats}
|
||
initialFormatId={initialTab}
|
||
liveBusy={liveBusy}
|
||
liveLabel="С роутера"
|
||
onLiveFetch={
|
||
onRequestLiveExport
|
||
? (formatId) =>
|
||
onRequestLiveExport(
|
||
formatId === "peer" ? "peer-conf" : formatId === "conf" ? "conf" : "rsc",
|
||
)
|
||
: undefined
|
||
}
|
||
/>
|
||
)
|
||
}
|
||
|
||
export { WgExportSheet }
|