import { useCallback, useEffect, useState } from "react"; import { SelectMenuBasic } from "../components/SelectMenuBasic"; import { SettingsPageHeader } from "../components/SettingsPageheader"; import { IPv4Mode, IPv6Mode, LLDPMode, mDNSMode, NetworkSettings, NetworkState, TimeSyncMode, useNetworkStateStore } from "@/hooks/stores"; import { useJsonRpc } from "@/hooks/useJsonRpc"; import notifications from "@/notifications"; import { Button } from "@components/Button"; import { GridCard } from "@components/Card"; import InputField from "@components/InputField"; import { SettingsItem } from "./devices.$id.settings"; import dayjs from 'dayjs'; import relativeTime from 'dayjs/plugin/relativeTime'; dayjs.extend(relativeTime); const defaultNetworkSettings: NetworkSettings = { ipv4_mode: "unknown", ipv6_mode: "unknown", lldp_mode: "unknown", lldp_tx_tlvs: [], mdns_mode: "unknown", time_sync_mode: "unknown", } export function LifeTimeLabel({ lifetime }: { lifetime: string }) { if (lifetime == "") { return N/A; } const [remaining, setRemaining] = useState(null); useEffect(() => { setRemaining(dayjs(lifetime).fromNow()); const interval = setInterval(() => { setRemaining(dayjs(lifetime).fromNow()); }, 1000 * 30); return () => clearInterval(interval); }, [lifetime]); return <> {dayjs(lifetime).format()} {remaining && <> {" "} ({remaining}) } } export default function SettingsNetworkRoute() { const [send] = useJsonRpc(); const [networkState, setNetworkState] = useNetworkStateStore(state => [state, state.setNetworkState]); const [networkSettings, setNetworkSettings] = useState(defaultNetworkSettings); const [networkSettingsLoaded, setNetworkSettingsLoaded] = useState(false); const [dhcpLeaseExpiry, setDhcpLeaseExpiry] = useState(null); const [dhcpLeaseExpiryRemaining, setDhcpLeaseExpiryRemaining] = useState(null); const getNetworkSettings = useCallback(() => { setNetworkSettingsLoaded(false); send("getNetworkSettings", {}, resp => { if ("error" in resp) return; setNetworkSettings(resp.result as NetworkSettings); setNetworkSettingsLoaded(true); }); }, [send]); const getNetworkState = useCallback(() => { send("getNetworkState", {}, resp => { if ("error" in resp) return; console.log(resp.result); setNetworkState(resp.result as NetworkState); }); }, [send]); const handleRenewLease = useCallback(() => { send("renewDHCPLease", {}, resp => { if ("error" in resp) { notifications.error("Failed to renew lease: " + resp.error.message); } else { notifications.success("DHCP lease renewed"); getNetworkState(); } }); }, [send, getNetworkState]); useEffect(() => { getNetworkState(); getNetworkSettings(); }, [getNetworkState, getNetworkSettings]); const handleIpv4ModeChange = (value: IPv4Mode | string) => { setNetworkSettings({ ...networkSettings, ipv4_mode: value as IPv4Mode }); }; const handleIpv6ModeChange = (value: IPv6Mode | string) => { setNetworkSettings({ ...networkSettings, ipv6_mode: value as IPv6Mode }); }; const handleLldpModeChange = (value: LLDPMode | string) => { setNetworkSettings({ ...networkSettings, lldp_mode: value as LLDPMode }); }; const handleLldpTxTlvsChange = (value: string[]) => { setNetworkSettings({ ...networkSettings, lldp_tx_tlvs: value }); }; const handleMdnsModeChange = (value: mDNSMode | string) => { setNetworkSettings({ ...networkSettings, mdns_mode: value as mDNSMode }); }; const handleTimeSyncModeChange = (value: TimeSyncMode | string) => { setNetworkSettings({ ...networkSettings, time_sync_mode: value as TimeSyncMode }); }; const filterUnknown = useCallback((options: { value: string; label: string; }[]) => { if (!networkSettingsLoaded) return options; return options.filter(option => option.value !== "unknown"); }, [networkSettingsLoaded]); return (
} > {networkState?.mac_address}
Hostname for the device
Leave blank for default } > { console.log(e.target.value); }} />
Domain for the device
Leave blank to use DHCP provided domain, if there is no domain, use local } > { console.log(e.target.value); }} />
handleIpv4ModeChange(e.target.value)} disabled={!networkSettingsLoaded} options={filterUnknown([ { value: "dhcp", label: "DHCP" }, // { value: "static", label: "Static" }, ])} /> {networkState?.dhcp_lease && (

Current DHCP Lease

    {networkState?.dhcp_lease?.ip &&
  • IP: {networkState?.dhcp_lease?.ip}
  • } {networkState?.dhcp_lease?.netmask &&
  • Subnet: {networkState?.dhcp_lease?.netmask}
  • } {networkState?.dhcp_lease?.broadcast &&
  • Broadcast: {networkState?.dhcp_lease?.broadcast}
  • } {networkState?.dhcp_lease?.ttl &&
  • TTL: {networkState?.dhcp_lease?.ttl}
  • } {networkState?.dhcp_lease?.mtu &&
  • MTU: {networkState?.dhcp_lease?.mtu}
  • } {networkState?.dhcp_lease?.hostname &&
  • Hostname: {networkState?.dhcp_lease?.hostname}
  • } {networkState?.dhcp_lease?.domain &&
  • Domain: {networkState?.dhcp_lease?.domain}
  • } {networkState?.dhcp_lease?.routers &&
  • Gateway: {networkState?.dhcp_lease?.routers.join(", ")}
  • } {networkState?.dhcp_lease?.dns &&
  • DNS: {networkState?.dhcp_lease?.dns.join(", ")}
  • } {networkState?.dhcp_lease?.ntp_servers &&
  • NTP Servers: {networkState?.dhcp_lease?.ntp_servers.join(", ")}
  • } {networkState?.dhcp_lease?.server_id &&
  • Server ID: {networkState?.dhcp_lease?.server_id}
  • } {networkState?.dhcp_lease?.bootp_next_server &&
  • BootP Next Server: {networkState?.dhcp_lease?.bootp_next_server}
  • } {networkState?.dhcp_lease?.bootp_server_name &&
  • BootP Server Name: {networkState?.dhcp_lease?.bootp_server_name}
  • } {networkState?.dhcp_lease?.bootp_file &&
  • Boot File: {networkState?.dhcp_lease?.bootp_file}
  • } {networkState?.dhcp_lease?.lease_expiry &&
  • Lease Expiry:
  • } {/* {JSON.stringify(networkState?.dhcp_lease)} */}

)}
handleIpv6ModeChange(e.target.value)} disabled={!networkSettingsLoaded} options={filterUnknown([ // { value: "disabled", label: "Disabled" }, { value: "slaac", label: "SLAAC" }, // { value: "dhcpv6", label: "DHCPv6" }, // { value: "slaac_and_dhcpv6", label: "SLAAC and DHCPv6" }, // { value: "static", label: "Static" }, // { value: "link_local", label: "Link-local only" }, ])} /> {networkState?.ipv6_addresses && (

IPv6 Information

IPv6 Link-local

{networkState?.ipv6_link_local}

IPv6 Addresses

    {networkState?.ipv6_addresses && networkState?.ipv6_addresses.map(addr => (
  • {addr.address} {addr.valid_lifetime && <>
    - valid_lft: {" "} } {addr.preferred_lifetime && <>
    - pref_lft: {" "} }
  • ))}
)}
handleLldpModeChange(e.target.value)} disabled={!networkSettingsLoaded} options={filterUnknown([ { value: "disabled", label: "Disabled" }, { value: "basic", label: "Basic" }, { value: "all", label: "All" }, ])} />
handleMdnsModeChange(e.target.value)} disabled={!networkSettingsLoaded} options={filterUnknown([ { value: "disabled", label: "Disabled" }, { value: "auto", label: "Auto" }, { value: "ipv4_only", label: "IPv4 only" }, { value: "ipv6_only", label: "IPv6 only" }, ])} />
handleTimeSyncModeChange(e.target.value)} disabled={!networkSettingsLoaded} options={filterUnknown([ { value: "unknown", label: "..." }, { value: "auto", label: "Auto" }, { value: "ntp_only", label: "NTP only" }, { value: "ntp_and_http", label: "NTP and HTTP" }, { value: "http_only", label: "HTTP only" }, { value: "custom", label: "Custom" }, ])} />
); }