mirror of https://github.com/jetkvm/kvm.git
fix: add ConfirmDialog for renewing DHCP lease and improve network settings layout
- Integrated ConfirmDialog component to confirm DHCP lease renewal. - Enhanced the layout of network settings, including better organization of IPv4 and IPv6 information. - Updated state management for displaying network settings and lease information. - Improved user experience with clearer descriptions and structured UI elements.
This commit is contained in:
parent
fcf2dbab60
commit
df74cb111d
|
@ -1,6 +1,7 @@
|
||||||
import { useCallback, useEffect, useRef, useState } from "react";
|
import { useCallback, useEffect, useRef, useState } from "react";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import relativeTime from "dayjs/plugin/relativeTime";
|
import relativeTime from "dayjs/plugin/relativeTime";
|
||||||
|
import { ArrowPathIcon } from "@heroicons/react/24/outline";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
IPv4Mode,
|
IPv4Mode,
|
||||||
|
@ -23,6 +24,7 @@ import { SelectMenuBasic } from "../components/SelectMenuBasic";
|
||||||
|
|
||||||
import { SettingsItem } from "./devices.$id.settings";
|
import { SettingsItem } from "./devices.$id.settings";
|
||||||
import Fieldset from "../components/Fieldset";
|
import Fieldset from "../components/Fieldset";
|
||||||
|
import { ConfirmDialog } from "../components/ConfirmDialog";
|
||||||
|
|
||||||
dayjs.extend(relativeTime);
|
dayjs.extend(relativeTime);
|
||||||
|
|
||||||
|
@ -206,471 +208,492 @@ export default function SettingsNetworkRoute() {
|
||||||
[networkSettingsLoaded],
|
[networkSettingsLoaded],
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log("firstNetworkSettings", firstNetworkSettings.current);
|
const [showRenewLeaseConfirm, setShowRenewLeaseConfirm] = useState(false);
|
||||||
console.log("networkSettings", networkSettings);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fieldset disabled={!networkSettingsLoaded} className="space-y-4">
|
<>
|
||||||
<SettingsPageHeader title="Network" description="Configure your network settings" />
|
<Fieldset disabled={!networkSettingsLoaded} className="space-y-4">
|
||||||
<div className="space-y-4">
|
<SettingsPageHeader
|
||||||
<SettingsItem
|
title="Network"
|
||||||
title="MAC Address"
|
description="Configure your network settings"
|
||||||
description="Hardware identifier for the network interface"
|
/>
|
||||||
>
|
|
||||||
<InputField
|
|
||||||
type="text"
|
|
||||||
size="SM"
|
|
||||||
value={networkState?.mac_address}
|
|
||||||
error={""}
|
|
||||||
disabled={true}
|
|
||||||
readOnly={true}
|
|
||||||
className="dark:!text-opacity-60"
|
|
||||||
/>
|
|
||||||
</SettingsItem>
|
|
||||||
</div>
|
|
||||||
<div className="space-y-4">
|
|
||||||
<SettingsItem
|
|
||||||
title="Hostname"
|
|
||||||
description="Device identifier on the network. Blank for system default"
|
|
||||||
>
|
|
||||||
<div className="relative">
|
|
||||||
<div>
|
|
||||||
<InputField
|
|
||||||
size="SM"
|
|
||||||
type="text"
|
|
||||||
placeholder="jetkvm"
|
|
||||||
defaultValue={networkSettings.hostname}
|
|
||||||
onChange={e => {
|
|
||||||
handleHostnameChange(e.target.value);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</SettingsItem>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="space-y-4">
|
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<SettingsItem title="Domain" description="Network domain suffix for the device">
|
<SettingsItem
|
||||||
<div className="space-y-2">
|
title="MAC Address"
|
||||||
<SelectMenuBasic
|
description="Hardware identifier for the network interface"
|
||||||
size="SM"
|
>
|
||||||
value={selectedDomainOption}
|
<InputField
|
||||||
onChange={e => handleDomainOptionChange(e.target.value)}
|
type="text"
|
||||||
options={[
|
size="SM"
|
||||||
{ value: "dhcp", label: "DHCP provided" },
|
value={networkState?.mac_address}
|
||||||
{ value: "local", label: ".local" },
|
error={""}
|
||||||
{ value: "custom", label: "Custom" },
|
disabled={true}
|
||||||
]}
|
readOnly={true}
|
||||||
/>
|
className="dark:!text-opacity-60"
|
||||||
|
/>
|
||||||
|
</SettingsItem>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-4">
|
||||||
|
<SettingsItem
|
||||||
|
title="Hostname"
|
||||||
|
description="Device identifier on the network. Blank for system default"
|
||||||
|
>
|
||||||
|
<div className="relative">
|
||||||
|
<div>
|
||||||
|
<InputField
|
||||||
|
size="SM"
|
||||||
|
type="text"
|
||||||
|
placeholder="jetkvm"
|
||||||
|
defaultValue={networkSettings.hostname}
|
||||||
|
onChange={e => {
|
||||||
|
handleHostnameChange(e.target.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</SettingsItem>
|
</SettingsItem>
|
||||||
{selectedDomainOption === "custom" && (
|
</div>
|
||||||
<div className="flex items-center justify-between gap-x-2">
|
|
||||||
<InputField
|
<div className="space-y-4">
|
||||||
|
<div className="space-y-4">
|
||||||
|
<SettingsItem
|
||||||
|
title="Domain"
|
||||||
|
description="Network domain suffix for the device"
|
||||||
|
>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<SelectMenuBasic
|
||||||
|
size="SM"
|
||||||
|
value={selectedDomainOption}
|
||||||
|
onChange={e => handleDomainOptionChange(e.target.value)}
|
||||||
|
options={[
|
||||||
|
{ value: "dhcp", label: "DHCP provided" },
|
||||||
|
{ value: "local", label: ".local" },
|
||||||
|
{ value: "custom", label: "Custom" },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</SettingsItem>
|
||||||
|
{selectedDomainOption === "custom" && (
|
||||||
|
<div className="flex items-center justify-between gap-x-2">
|
||||||
|
<InputField
|
||||||
|
size="SM"
|
||||||
|
type="text"
|
||||||
|
placeholder="home"
|
||||||
|
value={customDomain}
|
||||||
|
onChange={e => setCustomDomain(e.target.value)}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
size="SM"
|
||||||
|
theme="primary"
|
||||||
|
text="Save Domain"
|
||||||
|
onClick={() => handleCustomDomainChange(customDomain)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="space-y-4">
|
||||||
|
<SettingsItem
|
||||||
|
title="mDNS"
|
||||||
|
description="Control mDNS (multicast DNS) operational mode"
|
||||||
|
>
|
||||||
|
<SelectMenuBasic
|
||||||
size="SM"
|
size="SM"
|
||||||
type="text"
|
value={networkSettings.mdns_mode}
|
||||||
placeholder="home"
|
onChange={e => handleMdnsModeChange(e.target.value)}
|
||||||
value={customDomain}
|
options={filterUnknown([
|
||||||
onChange={e => setCustomDomain(e.target.value)}
|
{ value: "disabled", label: "Disabled" },
|
||||||
|
{ value: "auto", label: "Auto" },
|
||||||
|
{ value: "ipv4_only", label: "IPv4 only" },
|
||||||
|
{ value: "ipv6_only", label: "IPv6 only" },
|
||||||
|
])}
|
||||||
/>
|
/>
|
||||||
<Button
|
</SettingsItem>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-4">
|
||||||
|
<SettingsItem
|
||||||
|
title="Time synchronization"
|
||||||
|
description="Configure time synchronization settings"
|
||||||
|
>
|
||||||
|
<SelectMenuBasic
|
||||||
size="SM"
|
size="SM"
|
||||||
theme="primary"
|
value={networkSettings.time_sync_mode}
|
||||||
text="Save Domain"
|
onChange={e => {
|
||||||
onClick={() => handleCustomDomainChange(customDomain)}
|
handleTimeSyncModeChange(e.target.value);
|
||||||
|
}}
|
||||||
|
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" },
|
||||||
|
])}
|
||||||
/>
|
/>
|
||||||
</div>
|
</SettingsItem>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
size="SM"
|
||||||
|
theme="primary"
|
||||||
|
disabled={firstNetworkSettings.current === networkSettings}
|
||||||
|
text="Save Settings"
|
||||||
|
onClick={() => setNetworkSettingsRemote(networkSettings)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="h-[1px] w-full bg-slate-800/10 dark:bg-slate-300/20" />
|
||||||
|
|
||||||
|
<div className="space-y-4">
|
||||||
|
<SettingsItem title="IPv4 Mode" description="Configure the IPv4 mode">
|
||||||
|
<SelectMenuBasic
|
||||||
|
size="SM"
|
||||||
|
value={networkSettings.ipv4_mode}
|
||||||
|
onChange={e => handleIpv4ModeChange(e.target.value)}
|
||||||
|
options={filterUnknown([
|
||||||
|
{ value: "dhcp", label: "DHCP" },
|
||||||
|
// { value: "static", label: "Static" },
|
||||||
|
])}
|
||||||
|
/>
|
||||||
|
</SettingsItem>
|
||||||
|
{networkState?.dhcp_lease && (
|
||||||
|
<GridCard>
|
||||||
|
<div className="p-4">
|
||||||
|
<div className="space-y-4">
|
||||||
|
<h3 className="text-base font-bold text-slate-900 dark:text-white">
|
||||||
|
DHCP Lease
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<div className="flex gap-x-6 gap-y-2">
|
||||||
|
<div className="flex-1 space-y-2">
|
||||||
|
{networkState?.dhcp_lease?.ip && (
|
||||||
|
<div className="flex justify-between border-slate-800/10 pt-2 dark:border-slate-300/20">
|
||||||
|
<span className="text-sm text-slate-600 dark:text-slate-400">
|
||||||
|
IP Address
|
||||||
|
</span>
|
||||||
|
<span className="text-sm font-medium">
|
||||||
|
{networkState?.dhcp_lease?.ip}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{networkState?.dhcp_lease?.netmask && (
|
||||||
|
<div className="flex justify-between border-t border-slate-800/10 pt-2 dark:border-slate-300/20">
|
||||||
|
<span className="text-sm text-slate-600 dark:text-slate-400">
|
||||||
|
Subnet Mask
|
||||||
|
</span>
|
||||||
|
<span className="text-sm font-medium">
|
||||||
|
{networkState?.dhcp_lease?.netmask}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{networkState?.dhcp_lease?.dns && (
|
||||||
|
<div className="flex justify-between border-t border-slate-800/10 pt-2 dark:border-slate-300/20">
|
||||||
|
<span className="text-sm text-slate-600 dark:text-slate-400">
|
||||||
|
DNS Servers
|
||||||
|
</span>
|
||||||
|
<span className="text-right text-sm font-medium">
|
||||||
|
{networkState?.dhcp_lease?.dns.map(dns => (
|
||||||
|
<div key={dns}>{dns}</div>
|
||||||
|
))}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{networkState?.dhcp_lease?.broadcast && (
|
||||||
|
<div className="flex justify-between border-t border-slate-800/10 pt-2 dark:border-slate-300/20">
|
||||||
|
<span className="text-sm text-slate-600 dark:text-slate-400">
|
||||||
|
Broadcast
|
||||||
|
</span>
|
||||||
|
<span className="text-sm font-medium">
|
||||||
|
{networkState?.dhcp_lease?.broadcast}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{networkState?.dhcp_lease?.domain && (
|
||||||
|
<div className="flex justify-between border-t border-slate-800/10 pt-2 dark:border-slate-300/20">
|
||||||
|
<span className="text-sm text-slate-600 dark:text-slate-400">
|
||||||
|
Domain
|
||||||
|
</span>
|
||||||
|
<span className="text-sm font-medium">
|
||||||
|
{networkState?.dhcp_lease?.domain}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{networkState?.dhcp_lease?.ntp_servers &&
|
||||||
|
networkState?.dhcp_lease?.ntp_servers.length > 0 && (
|
||||||
|
<div className="flex justify-between gap-x-8 border-t border-slate-800/10 pt-2 dark:border-slate-300/20">
|
||||||
|
<div className="w-full grow text-sm text-slate-600 dark:text-slate-400">
|
||||||
|
NTP Servers
|
||||||
|
</div>
|
||||||
|
<div className="shrink text-right text-sm font-medium">
|
||||||
|
{networkState?.dhcp_lease?.ntp_servers.map(server => (
|
||||||
|
<div key={server}>{server}</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{networkState?.dhcp_lease?.hostname && (
|
||||||
|
<div className="flex justify-between border-t border-slate-800/10 pt-2 dark:border-slate-300/20">
|
||||||
|
<span className="text-sm text-slate-600 dark:text-slate-400">
|
||||||
|
Hostname
|
||||||
|
</span>
|
||||||
|
<span className="text-sm font-medium">
|
||||||
|
{networkState?.dhcp_lease?.hostname}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex-1 space-y-2">
|
||||||
|
{networkState?.dhcp_lease?.routers &&
|
||||||
|
networkState?.dhcp_lease?.routers.length > 0 && (
|
||||||
|
<div className="flex justify-between pt-2">
|
||||||
|
<span className="text-sm text-slate-600 dark:text-slate-400">
|
||||||
|
Gateway
|
||||||
|
</span>
|
||||||
|
<span className="text-right text-sm font-medium">
|
||||||
|
{networkState?.dhcp_lease?.routers.map(router => (
|
||||||
|
<div key={router}>{router}</div>
|
||||||
|
))}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{networkState?.dhcp_lease?.server_id && (
|
||||||
|
<div className="flex justify-between border-t border-slate-800/10 pt-2 dark:border-slate-300/20">
|
||||||
|
<span className="text-sm text-slate-600 dark:text-slate-400">
|
||||||
|
DHCP Server
|
||||||
|
</span>
|
||||||
|
<span className="text-sm font-medium">
|
||||||
|
{networkState?.dhcp_lease?.server_id}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{networkState?.dhcp_lease?.lease_expiry && (
|
||||||
|
<div className="flex justify-between border-t border-slate-800/10 pt-2 dark:border-slate-300/20">
|
||||||
|
<span className="text-sm text-slate-600 dark:text-slate-400">
|
||||||
|
Lease Expires
|
||||||
|
</span>
|
||||||
|
<span className="text-sm font-medium">
|
||||||
|
<LifeTimeLabel
|
||||||
|
lifetime={`${networkState?.dhcp_lease?.lease_expiry}`}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{networkState?.dhcp_lease?.mtu && (
|
||||||
|
<div className="flex justify-between border-t border-slate-800/10 pt-2 dark:border-slate-300/20">
|
||||||
|
<span className="text-sm text-slate-600 dark:text-slate-400">
|
||||||
|
MTU
|
||||||
|
</span>
|
||||||
|
<span className="text-sm font-medium">
|
||||||
|
{networkState?.dhcp_lease?.mtu}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{networkState?.dhcp_lease?.ttl && (
|
||||||
|
<div className="flex justify-between border-t border-slate-800/10 pt-2 dark:border-slate-300/20">
|
||||||
|
<span className="text-sm text-slate-600 dark:text-slate-400">
|
||||||
|
TTL
|
||||||
|
</span>
|
||||||
|
<span className="text-sm font-medium">
|
||||||
|
{networkState?.dhcp_lease?.ttl}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{networkState?.dhcp_lease?.bootp_next_server && (
|
||||||
|
<div className="flex justify-between border-t border-slate-800/10 pt-2 dark:border-slate-300/20">
|
||||||
|
<span className="text-sm text-slate-600 dark:text-slate-400">
|
||||||
|
Boot Next Server
|
||||||
|
</span>
|
||||||
|
<span className="text-sm font-medium">
|
||||||
|
{networkState?.dhcp_lease?.bootp_next_server}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{networkState?.dhcp_lease?.bootp_server_name && (
|
||||||
|
<div className="flex justify-between border-t border-slate-800/10 pt-2 dark:border-slate-300/20">
|
||||||
|
<span className="text-sm text-slate-600 dark:text-slate-400">
|
||||||
|
Boot Server Name
|
||||||
|
</span>
|
||||||
|
<span className="text-sm font-medium">
|
||||||
|
{networkState?.dhcp_lease?.bootp_server_name}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{networkState?.dhcp_lease?.bootp_file && (
|
||||||
|
<div className="flex justify-between border-t border-slate-800/10 pt-2 dark:border-slate-300/20">
|
||||||
|
<span className="text-sm text-slate-600 dark:text-slate-400">
|
||||||
|
Boot File
|
||||||
|
</span>
|
||||||
|
<span className="text-sm font-medium">
|
||||||
|
{networkState?.dhcp_lease?.bootp_file}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Button
|
||||||
|
size="SM"
|
||||||
|
theme="light"
|
||||||
|
className="text-red-500"
|
||||||
|
text="Renew DHCP Lease"
|
||||||
|
LeadingIcon={ArrowPathIcon}
|
||||||
|
onClick={() => setShowRenewLeaseConfirm(true)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</GridCard>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
|
<SettingsItem title="IPv6 Mode" description="Configure the IPv6 mode">
|
||||||
|
<SelectMenuBasic
|
||||||
|
size="SM"
|
||||||
|
value={networkSettings.ipv6_mode}
|
||||||
|
onChange={e => handleIpv6ModeChange(e.target.value)}
|
||||||
|
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" },
|
||||||
|
])}
|
||||||
|
/>
|
||||||
|
</SettingsItem>
|
||||||
|
{networkState?.ipv6_addresses && (
|
||||||
|
<GridCard>
|
||||||
|
<div className="p-4">
|
||||||
|
<div className="space-y-4">
|
||||||
|
<h3 className="text-base font-bold text-slate-900 dark:text-white">
|
||||||
|
IPv6 Information
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-2 gap-x-6 gap-y-2">
|
||||||
|
{networkState?.dhcp_lease?.ip && (
|
||||||
|
<div className="flex flex-col justify-between">
|
||||||
|
<span className="text-sm text-slate-600 dark:text-slate-400">
|
||||||
|
Link-local
|
||||||
|
</span>
|
||||||
|
<span className="text-sm font-medium">
|
||||||
|
{networkState?.ipv6_link_local}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-3 pt-2">
|
||||||
|
{networkState?.ipv6_addresses &&
|
||||||
|
networkState?.ipv6_addresses.length > 0 && (
|
||||||
|
<div className="space-y-3">
|
||||||
|
<h4 className="text-sm font-semibold">IPv6 Addresses</h4>
|
||||||
|
{networkState.ipv6_addresses.map(addr => (
|
||||||
|
<div
|
||||||
|
key={addr.address}
|
||||||
|
className="rounded-md rounded-l-none border border-slate-500/10 border-l-blue-700/50 bg-slate-100/40 p-4 pl-4 dark:border-blue-500 dark:bg-slate-900"
|
||||||
|
>
|
||||||
|
<div className="grid grid-cols-2 gap-x-8 gap-y-4">
|
||||||
|
<div className="col-span-2 flex flex-col justify-between">
|
||||||
|
<span className="text-sm text-slate-600 dark:text-slate-400">
|
||||||
|
Address
|
||||||
|
</span>
|
||||||
|
<span className="text-sm font-medium">
|
||||||
|
{addr.address}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{addr.valid_lifetime && (
|
||||||
|
<div className="flex flex-col justify-between">
|
||||||
|
<span className="text-sm text-slate-600 dark:text-slate-400">
|
||||||
|
Valid Lifetime
|
||||||
|
</span>
|
||||||
|
<span className="text-sm font-medium">
|
||||||
|
{addr.valid_lifetime === "" ? (
|
||||||
|
<span className="text-slate-400 dark:text-slate-600">
|
||||||
|
N/A
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<LifeTimeLabel
|
||||||
|
lifetime={`${addr.valid_lifetime}`}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{addr.preferred_lifetime && (
|
||||||
|
<div className="flex flex-col justify-between">
|
||||||
|
<span className="text-sm text-slate-600 dark:text-slate-400">
|
||||||
|
Preferred Lifetime
|
||||||
|
</span>
|
||||||
|
<span className="text-sm font-medium">
|
||||||
|
{addr.preferred_lifetime === "" ? (
|
||||||
|
<span className="text-slate-400 dark:text-slate-600">
|
||||||
|
N/A
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<LifeTimeLabel
|
||||||
|
lifetime={`${addr.preferred_lifetime}`}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</GridCard>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="hidden space-y-4">
|
||||||
<SettingsItem
|
<SettingsItem
|
||||||
title="mDNS"
|
title="LLDP"
|
||||||
description="Control mDNS (multicast DNS) operational mode"
|
description="Control which TLVs will be sent over Link Layer Discovery Protocol"
|
||||||
>
|
>
|
||||||
<SelectMenuBasic
|
<SelectMenuBasic
|
||||||
size="SM"
|
size="SM"
|
||||||
value={networkSettings.mdns_mode}
|
value={networkSettings.lldp_mode}
|
||||||
onChange={e => handleMdnsModeChange(e.target.value)}
|
onChange={e => handleLldpModeChange(e.target.value)}
|
||||||
options={filterUnknown([
|
options={filterUnknown([
|
||||||
{ value: "disabled", label: "Disabled" },
|
{ value: "disabled", label: "Disabled" },
|
||||||
{ value: "auto", label: "Auto" },
|
{ value: "basic", label: "Basic" },
|
||||||
{ value: "ipv4_only", label: "IPv4 only" },
|
{ value: "all", label: "All" },
|
||||||
{ value: "ipv6_only", label: "IPv6 only" },
|
|
||||||
])}
|
])}
|
||||||
/>
|
/>
|
||||||
</SettingsItem>
|
</SettingsItem>
|
||||||
</div>
|
</div>
|
||||||
|
</Fieldset>
|
||||||
<div className="space-y-4">
|
<ConfirmDialog
|
||||||
<SettingsItem
|
open={showRenewLeaseConfirm}
|
||||||
title="Time synchronization"
|
onClose={() => setShowRenewLeaseConfirm(false)}
|
||||||
description="Configure time synchronization settings"
|
title="Renew DHCP Lease"
|
||||||
>
|
description="This will request a new IP address from your DHCP server. Your device may temporarily lose network connectivity during this process."
|
||||||
<SelectMenuBasic
|
variant="danger"
|
||||||
size="SM"
|
confirmText="Renew Lease"
|
||||||
value={networkSettings.time_sync_mode}
|
onConfirm={() => {
|
||||||
onChange={e => {
|
handleRenewLease();
|
||||||
handleTimeSyncModeChange(e.target.value);
|
setShowRenewLeaseConfirm(false);
|
||||||
}}
|
}}
|
||||||
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" },
|
|
||||||
])}
|
|
||||||
/>
|
|
||||||
</SettingsItem>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
size="SM"
|
|
||||||
theme="primary"
|
|
||||||
disabled={firstNetworkSettings.current === networkSettings}
|
|
||||||
text="Save Settings"
|
|
||||||
onClick={() => setNetworkSettingsRemote(networkSettings)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="h-[1px] w-full bg-slate-800/10 dark:bg-slate-300/20" />
|
|
||||||
|
|
||||||
<div className="space-y-4">
|
|
||||||
<SettingsItem title="IPv4 Mode" description="Configure the IPv4 mode">
|
|
||||||
<SelectMenuBasic
|
|
||||||
size="SM"
|
|
||||||
value={networkSettings.ipv4_mode}
|
|
||||||
onChange={e => handleIpv4ModeChange(e.target.value)}
|
|
||||||
options={filterUnknown([
|
|
||||||
{ value: "dhcp", label: "DHCP" },
|
|
||||||
// { value: "static", label: "Static" },
|
|
||||||
])}
|
|
||||||
/>
|
|
||||||
</SettingsItem>
|
|
||||||
{networkState?.dhcp_lease && (
|
|
||||||
<GridCard>
|
|
||||||
<div className="p-4">
|
|
||||||
<div className="space-y-4">
|
|
||||||
<h3 className="text-base font-bold text-slate-900 dark:text-white">
|
|
||||||
Current DHCP Lease
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<div className="flex gap-x-6 gap-y-2">
|
|
||||||
<div className="flex-1 space-y-2">
|
|
||||||
{networkState?.dhcp_lease?.ip && (
|
|
||||||
<div className="flex justify-between border-slate-800/10 pt-2 dark:border-slate-300/20">
|
|
||||||
<span className="text-sm text-slate-600 dark:text-slate-400">
|
|
||||||
IP Address
|
|
||||||
</span>
|
|
||||||
<span className="text-sm font-medium">
|
|
||||||
{networkState?.dhcp_lease?.ip}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{networkState?.dhcp_lease?.netmask && (
|
|
||||||
<div className="flex justify-between border-t border-slate-800/10 pt-2 dark:border-slate-300/20">
|
|
||||||
<span className="text-sm text-slate-600 dark:text-slate-400">
|
|
||||||
Subnet Mask
|
|
||||||
</span>
|
|
||||||
<span className="text-sm font-medium">
|
|
||||||
{networkState?.dhcp_lease?.netmask}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{networkState?.dhcp_lease?.dns && (
|
|
||||||
<div className="flex justify-between border-t border-slate-800/10 pt-2 dark:border-slate-300/20">
|
|
||||||
<span className="text-sm text-slate-600 dark:text-slate-400">
|
|
||||||
DNS Servers
|
|
||||||
</span>
|
|
||||||
<span className="text-right text-sm font-medium">
|
|
||||||
{networkState?.dhcp_lease?.dns.map(dns => (
|
|
||||||
<div key={dns}>{dns}</div>
|
|
||||||
))}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{networkState?.dhcp_lease?.broadcast && (
|
|
||||||
<div className="flex justify-between border-t border-slate-800/10 pt-2 dark:border-slate-300/20">
|
|
||||||
<span className="text-sm text-slate-600 dark:text-slate-400">
|
|
||||||
Broadcast
|
|
||||||
</span>
|
|
||||||
<span className="text-sm font-medium">
|
|
||||||
{networkState?.dhcp_lease?.broadcast}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{networkState?.dhcp_lease?.domain && (
|
|
||||||
<div className="flex justify-between border-t border-slate-800/10 pt-2 dark:border-slate-300/20">
|
|
||||||
<span className="text-sm text-slate-600 dark:text-slate-400">
|
|
||||||
Domain
|
|
||||||
</span>
|
|
||||||
<span className="text-sm font-medium">
|
|
||||||
{networkState?.dhcp_lease?.domain}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{networkState?.dhcp_lease?.ntp_servers &&
|
|
||||||
networkState?.dhcp_lease?.ntp_servers.length > 0 && (
|
|
||||||
<div className="flex justify-between gap-x-8 border-t border-slate-800/10 pt-2 dark:border-slate-300/20">
|
|
||||||
<div className="w-full grow text-sm text-slate-600 dark:text-slate-400">
|
|
||||||
NTP Servers
|
|
||||||
</div>
|
|
||||||
<div className="shrink text-right text-sm font-medium">
|
|
||||||
{networkState?.dhcp_lease?.ntp_servers.map(server => (
|
|
||||||
<div key={server}>{server}</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{networkState?.dhcp_lease?.hostname && (
|
|
||||||
<div className="flex justify-between border-t border-slate-800/10 pt-2 dark:border-slate-300/20">
|
|
||||||
<span className="text-sm text-slate-600 dark:text-slate-400">
|
|
||||||
Hostname
|
|
||||||
</span>
|
|
||||||
<span className="text-sm font-medium">
|
|
||||||
{networkState?.dhcp_lease?.hostname}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex-1 space-y-2">
|
|
||||||
{networkState?.dhcp_lease?.routers &&
|
|
||||||
networkState?.dhcp_lease?.routers.length > 0 && (
|
|
||||||
<div className="flex justify-between pt-2">
|
|
||||||
<span className="text-sm text-slate-600 dark:text-slate-400">
|
|
||||||
Gateway
|
|
||||||
</span>
|
|
||||||
<span className="text-right text-sm font-medium">
|
|
||||||
{networkState?.dhcp_lease?.routers.map(router => (
|
|
||||||
<div key={router}>{router}</div>
|
|
||||||
))}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{networkState?.dhcp_lease?.server_id && (
|
|
||||||
<div className="flex justify-between border-t border-slate-800/10 pt-2 dark:border-slate-300/20">
|
|
||||||
<span className="text-sm text-slate-600 dark:text-slate-400">
|
|
||||||
DHCP Server
|
|
||||||
</span>
|
|
||||||
<span className="text-sm font-medium">
|
|
||||||
{networkState?.dhcp_lease?.server_id}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{networkState?.dhcp_lease?.lease_expiry && (
|
|
||||||
<div className="flex justify-between border-t border-slate-800/10 pt-2 dark:border-slate-300/20">
|
|
||||||
<span className="text-sm text-slate-600 dark:text-slate-400">
|
|
||||||
Lease Expires
|
|
||||||
</span>
|
|
||||||
<span className="text-sm font-medium">
|
|
||||||
<LifeTimeLabel
|
|
||||||
lifetime={`${networkState?.dhcp_lease?.lease_expiry}`}
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{networkState?.dhcp_lease?.mtu && (
|
|
||||||
<div className="flex justify-between border-t border-slate-800/10 pt-2 dark:border-slate-300/20">
|
|
||||||
<span className="text-sm text-slate-600 dark:text-slate-400">
|
|
||||||
MTU
|
|
||||||
</span>
|
|
||||||
<span className="text-sm font-medium">
|
|
||||||
{networkState?.dhcp_lease?.mtu}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{networkState?.dhcp_lease?.ttl && (
|
|
||||||
<div className="flex justify-between border-t border-slate-800/10 pt-2 dark:border-slate-300/20">
|
|
||||||
<span className="text-sm text-slate-600 dark:text-slate-400">
|
|
||||||
TTL
|
|
||||||
</span>
|
|
||||||
<span className="text-sm font-medium">
|
|
||||||
{networkState?.dhcp_lease?.ttl}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{networkState?.dhcp_lease?.bootp_next_server && (
|
|
||||||
<div className="flex justify-between border-t border-slate-800/10 pt-2 dark:border-slate-300/20">
|
|
||||||
<span className="text-sm text-slate-600 dark:text-slate-400">
|
|
||||||
Boot Next Server
|
|
||||||
</span>
|
|
||||||
<span className="text-sm font-medium">
|
|
||||||
{networkState?.dhcp_lease?.bootp_next_server}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{networkState?.dhcp_lease?.bootp_server_name && (
|
|
||||||
<div className="flex justify-between border-t border-slate-800/10 pt-2 dark:border-slate-300/20">
|
|
||||||
<span className="text-sm text-slate-600 dark:text-slate-400">
|
|
||||||
Boot Server Name
|
|
||||||
</span>
|
|
||||||
<span className="text-sm font-medium">
|
|
||||||
{networkState?.dhcp_lease?.bootp_server_name}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{networkState?.dhcp_lease?.bootp_file && (
|
|
||||||
<div className="flex justify-between border-t border-slate-800/10 pt-2 dark:border-slate-300/20">
|
|
||||||
<span className="text-sm text-slate-600 dark:text-slate-400">
|
|
||||||
Boot File
|
|
||||||
</span>
|
|
||||||
<span className="text-sm font-medium">
|
|
||||||
{networkState?.dhcp_lease?.bootp_file}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<Button
|
|
||||||
size="SM"
|
|
||||||
theme="primary"
|
|
||||||
text="Renew lease"
|
|
||||||
onClick={handleRenewLease}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</GridCard>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div className="space-y-4">
|
|
||||||
<SettingsItem title="IPv6 Mode" description="Configure the IPv6 mode">
|
|
||||||
<SelectMenuBasic
|
|
||||||
size="SM"
|
|
||||||
value={networkSettings.ipv6_mode}
|
|
||||||
onChange={e => handleIpv6ModeChange(e.target.value)}
|
|
||||||
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" },
|
|
||||||
])}
|
|
||||||
/>
|
|
||||||
</SettingsItem>
|
|
||||||
{networkState?.ipv6_addresses && (
|
|
||||||
<GridCard>
|
|
||||||
<div className="p-4">
|
|
||||||
<div className="space-y-4">
|
|
||||||
<h3 className="text-base font-bold text-slate-900 dark:text-white">
|
|
||||||
IPv6 Information
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<div className="grid grid-cols-2 gap-x-6 gap-y-2">
|
|
||||||
{networkState?.dhcp_lease?.ip && (
|
|
||||||
<div className="flex flex-col justify-between">
|
|
||||||
<span className="text-sm text-slate-600 dark:text-slate-400">
|
|
||||||
Link-local
|
|
||||||
</span>
|
|
||||||
<span className="text-sm font-medium">
|
|
||||||
{networkState?.ipv6_link_local}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="space-y-3 pt-2">
|
|
||||||
{networkState?.ipv6_addresses &&
|
|
||||||
networkState?.ipv6_addresses.length > 0 && (
|
|
||||||
<div className="space-y-3">
|
|
||||||
<h4 className="text-sm font-semibold">IPv6 Addresses</h4>
|
|
||||||
{networkState.ipv6_addresses.map(addr => (
|
|
||||||
<div
|
|
||||||
key={addr.address}
|
|
||||||
className="rounded-md rounded-l-none border border-slate-500/10 border-l-blue-700/50 bg-slate-100/40 p-4 pl-4 dark:border-blue-500 dark:bg-slate-900"
|
|
||||||
>
|
|
||||||
<div className="grid grid-cols-2 gap-x-8 gap-y-4">
|
|
||||||
<div className="col-span-2 flex flex-col justify-between">
|
|
||||||
<span className="text-sm text-slate-600 dark:text-slate-400">
|
|
||||||
Address
|
|
||||||
</span>
|
|
||||||
<span className="text-sm font-medium">
|
|
||||||
{addr.address}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{addr.valid_lifetime && (
|
|
||||||
<div className="flex flex-col justify-between">
|
|
||||||
<span className="text-sm text-slate-600 dark:text-slate-400">
|
|
||||||
Valid Lifetime
|
|
||||||
</span>
|
|
||||||
<span className="text-sm font-medium">
|
|
||||||
{addr.valid_lifetime === "" ? (
|
|
||||||
<span className="text-slate-400 dark:text-slate-600">
|
|
||||||
N/A
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
<LifeTimeLabel
|
|
||||||
lifetime={`${addr.valid_lifetime}`}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{addr.preferred_lifetime && (
|
|
||||||
<div className="flex flex-col justify-between">
|
|
||||||
<span className="text-sm text-slate-600 dark:text-slate-400">
|
|
||||||
Preferred Lifetime
|
|
||||||
</span>
|
|
||||||
<span className="text-sm font-medium">
|
|
||||||
{addr.preferred_lifetime === "" ? (
|
|
||||||
<span className="text-slate-400 dark:text-slate-600">
|
|
||||||
N/A
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
<LifeTimeLabel
|
|
||||||
lifetime={`${addr.preferred_lifetime}`}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</GridCard>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div className="hidden space-y-4">
|
|
||||||
<SettingsItem
|
|
||||||
title="LLDP"
|
|
||||||
description="Control which TLVs will be sent over Link Layer Discovery Protocol"
|
|
||||||
>
|
|
||||||
<SelectMenuBasic
|
|
||||||
size="SM"
|
|
||||||
value={networkSettings.lldp_mode}
|
|
||||||
onChange={e => handleLldpModeChange(e.target.value)}
|
|
||||||
options={filterUnknown([
|
|
||||||
{ value: "disabled", label: "Disabled" },
|
|
||||||
{ value: "basic", label: "Basic" },
|
|
||||||
{ value: "all", label: "All" },
|
|
||||||
])}
|
|
||||||
/>
|
|
||||||
</SettingsItem>
|
|
||||||
</div>
|
|
||||||
</Fieldset>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue