From df74cb111d81d2554d7f0d53912599e4d853af65 Mon Sep 17 00:00:00 2001 From: Adam Shiervani Date: Wed, 16 Apr 2025 22:01:10 +0200 Subject: [PATCH] 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. --- ui/src/components/ConfirmDialog.tsx | 2 +- .../routes/devices.$id.settings.network.tsx | 911 +++++++++--------- 2 files changed, 468 insertions(+), 445 deletions(-) diff --git a/ui/src/components/ConfirmDialog.tsx b/ui/src/components/ConfirmDialog.tsx index 57391e2..6dbff8c 100644 --- a/ui/src/components/ConfirmDialog.tsx +++ b/ui/src/components/ConfirmDialog.tsx @@ -103,4 +103,4 @@ export function ConfirmDialog({ ); -} \ No newline at end of file +} diff --git a/ui/src/routes/devices.$id.settings.network.tsx b/ui/src/routes/devices.$id.settings.network.tsx index d2e8703..a96c08b 100644 --- a/ui/src/routes/devices.$id.settings.network.tsx +++ b/ui/src/routes/devices.$id.settings.network.tsx @@ -1,6 +1,7 @@ import { useCallback, useEffect, useRef, useState } from "react"; import dayjs from "dayjs"; import relativeTime from "dayjs/plugin/relativeTime"; +import { ArrowPathIcon } from "@heroicons/react/24/outline"; import { IPv4Mode, @@ -23,6 +24,7 @@ import { SelectMenuBasic } from "../components/SelectMenuBasic"; import { SettingsItem } from "./devices.$id.settings"; import Fieldset from "../components/Fieldset"; +import { ConfirmDialog } from "../components/ConfirmDialog"; dayjs.extend(relativeTime); @@ -206,471 +208,492 @@ export default function SettingsNetworkRoute() { [networkSettingsLoaded], ); - console.log("firstNetworkSettings", firstNetworkSettings.current); - console.log("networkSettings", networkSettings); + const [showRenewLeaseConfirm, setShowRenewLeaseConfirm] = useState(false); return ( -
- -
- - - -
-
- -
-
- { - handleHostnameChange(e.target.value); - }} - /> -
-
-
-
- -
+ <> +
+
- -
- handleDomainOptionChange(e.target.value)} - options={[ - { value: "dhcp", label: "DHCP provided" }, - { value: "local", label: ".local" }, - { value: "custom", label: "Custom" }, - ]} - /> + + + +
+
+ +
+
+ { + handleHostnameChange(e.target.value); + }} + /> +
- {selectedDomainOption === "custom" && ( -
- + +
+
+ +
+ handleDomainOptionChange(e.target.value)} + options={[ + { value: "dhcp", label: "DHCP provided" }, + { value: "local", label: ".local" }, + { value: "custom", label: "Custom" }, + ]} + /> +
+
+ {selectedDomainOption === "custom" && ( +
+ setCustomDomain(e.target.value)} + /> +
+ )} +
+
+ + setCustomDomain(e.target.value)} + value={networkSettings.mdns_mode} + onChange={e => handleMdnsModeChange(e.target.value)} + options={filterUnknown([ + { value: "disabled", label: "Disabled" }, + { value: "auto", label: "Auto" }, + { value: "ipv4_only", label: "IPv4 only" }, + { value: "ipv6_only", label: "IPv6 only" }, + ])} /> -
+ +
+ + handleCustomDomainChange(customDomain)} + value={networkSettings.time_sync_mode} + onChange={e => { + 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" }, + ])} /> -
+ +
+ +
+ +
+ +
+ + handleIpv4ModeChange(e.target.value)} + options={filterUnknown([ + { value: "dhcp", label: "DHCP" }, + // { value: "static", label: "Static" }, + ])} + /> + + {networkState?.dhcp_lease && ( + +
+
+

+ DHCP Lease +

+ +
+
+ {networkState?.dhcp_lease?.ip && ( +
+ + IP Address + + + {networkState?.dhcp_lease?.ip} + +
+ )} + + {networkState?.dhcp_lease?.netmask && ( +
+ + Subnet Mask + + + {networkState?.dhcp_lease?.netmask} + +
+ )} + + {networkState?.dhcp_lease?.dns && ( +
+ + DNS Servers + + + {networkState?.dhcp_lease?.dns.map(dns => ( +
{dns}
+ ))} +
+
+ )} + + {networkState?.dhcp_lease?.broadcast && ( +
+ + Broadcast + + + {networkState?.dhcp_lease?.broadcast} + +
+ )} + + {networkState?.dhcp_lease?.domain && ( +
+ + Domain + + + {networkState?.dhcp_lease?.domain} + +
+ )} + + {networkState?.dhcp_lease?.ntp_servers && + networkState?.dhcp_lease?.ntp_servers.length > 0 && ( +
+
+ NTP Servers +
+
+ {networkState?.dhcp_lease?.ntp_servers.map(server => ( +
{server}
+ ))} +
+
+ )} + + {networkState?.dhcp_lease?.hostname && ( +
+ + Hostname + + + {networkState?.dhcp_lease?.hostname} + +
+ )} +
+ +
+ {networkState?.dhcp_lease?.routers && + networkState?.dhcp_lease?.routers.length > 0 && ( +
+ + Gateway + + + {networkState?.dhcp_lease?.routers.map(router => ( +
{router}
+ ))} +
+
+ )} + + {networkState?.dhcp_lease?.server_id && ( +
+ + DHCP Server + + + {networkState?.dhcp_lease?.server_id} + +
+ )} + + {networkState?.dhcp_lease?.lease_expiry && ( +
+ + Lease Expires + + + + +
+ )} + + {networkState?.dhcp_lease?.mtu && ( +
+ + MTU + + + {networkState?.dhcp_lease?.mtu} + +
+ )} + + {networkState?.dhcp_lease?.ttl && ( +
+ + TTL + + + {networkState?.dhcp_lease?.ttl} + +
+ )} + + {networkState?.dhcp_lease?.bootp_next_server && ( +
+ + Boot Next Server + + + {networkState?.dhcp_lease?.bootp_next_server} + +
+ )} + + {networkState?.dhcp_lease?.bootp_server_name && ( +
+ + Boot Server Name + + + {networkState?.dhcp_lease?.bootp_server_name} + +
+ )} + + {networkState?.dhcp_lease?.bootp_file && ( +
+ + Boot File + + + {networkState?.dhcp_lease?.bootp_file} + +
+ )} +
+
+ +
+
+
+
+
)}
+ + 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" }, + ])} + /> + + {networkState?.ipv6_addresses && ( + +
+
+

+ IPv6 Information +

+ +
+ {networkState?.dhcp_lease?.ip && ( +
+ + Link-local + + + {networkState?.ipv6_link_local} + +
+ )} +
+ +
+ {networkState?.ipv6_addresses && + networkState?.ipv6_addresses.length > 0 && ( +
+

IPv6 Addresses

+ {networkState.ipv6_addresses.map(addr => ( +
+
+
+ + Address + + + {addr.address} + +
+ + {addr.valid_lifetime && ( +
+ + Valid Lifetime + + + {addr.valid_lifetime === "" ? ( + + N/A + + ) : ( + + )} + +
+ )} + {addr.preferred_lifetime && ( +
+ + Preferred Lifetime + + + {addr.preferred_lifetime === "" ? ( + + N/A + + ) : ( + + )} + +
+ )} +
+
+ ))} +
+ )} +
+
+
+
+ )} +
+
handleMdnsModeChange(e.target.value)} + value={networkSettings.lldp_mode} + onChange={e => handleLldpModeChange(e.target.value)} options={filterUnknown([ { value: "disabled", label: "Disabled" }, - { value: "auto", label: "Auto" }, - { value: "ipv4_only", label: "IPv4 only" }, - { value: "ipv6_only", label: "IPv6 only" }, + { value: "basic", label: "Basic" }, + { value: "all", label: "All" }, ])} />
- -
- - { - 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" }, - ])} - /> - -
- -
- -
- -
- - handleIpv4ModeChange(e.target.value)} - options={filterUnknown([ - { value: "dhcp", label: "DHCP" }, - // { value: "static", label: "Static" }, - ])} - /> - - {networkState?.dhcp_lease && ( - -
-
-

- Current DHCP Lease -

- -
-
- {networkState?.dhcp_lease?.ip && ( -
- - IP Address - - - {networkState?.dhcp_lease?.ip} - -
- )} - - {networkState?.dhcp_lease?.netmask && ( -
- - Subnet Mask - - - {networkState?.dhcp_lease?.netmask} - -
- )} - - {networkState?.dhcp_lease?.dns && ( -
- - DNS Servers - - - {networkState?.dhcp_lease?.dns.map(dns => ( -
{dns}
- ))} -
-
- )} - - {networkState?.dhcp_lease?.broadcast && ( -
- - Broadcast - - - {networkState?.dhcp_lease?.broadcast} - -
- )} - - {networkState?.dhcp_lease?.domain && ( -
- - Domain - - - {networkState?.dhcp_lease?.domain} - -
- )} - - {networkState?.dhcp_lease?.ntp_servers && - networkState?.dhcp_lease?.ntp_servers.length > 0 && ( -
-
- NTP Servers -
-
- {networkState?.dhcp_lease?.ntp_servers.map(server => ( -
{server}
- ))} -
-
- )} - - {networkState?.dhcp_lease?.hostname && ( -
- - Hostname - - - {networkState?.dhcp_lease?.hostname} - -
- )} -
- -
- {networkState?.dhcp_lease?.routers && - networkState?.dhcp_lease?.routers.length > 0 && ( -
- - Gateway - - - {networkState?.dhcp_lease?.routers.map(router => ( -
{router}
- ))} -
-
- )} - - {networkState?.dhcp_lease?.server_id && ( -
- - DHCP Server - - - {networkState?.dhcp_lease?.server_id} - -
- )} - - {networkState?.dhcp_lease?.lease_expiry && ( -
- - Lease Expires - - - - -
- )} - - {networkState?.dhcp_lease?.mtu && ( -
- - MTU - - - {networkState?.dhcp_lease?.mtu} - -
- )} - - {networkState?.dhcp_lease?.ttl && ( -
- - TTL - - - {networkState?.dhcp_lease?.ttl} - -
- )} - - {networkState?.dhcp_lease?.bootp_next_server && ( -
- - Boot Next Server - - - {networkState?.dhcp_lease?.bootp_next_server} - -
- )} - - {networkState?.dhcp_lease?.bootp_server_name && ( -
- - Boot Server Name - - - {networkState?.dhcp_lease?.bootp_server_name} - -
- )} - - {networkState?.dhcp_lease?.bootp_file && ( -
- - Boot File - - - {networkState?.dhcp_lease?.bootp_file} - -
- )} -
-
- -
-
-
-
-
- )} -
-
- - 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" }, - ])} - /> - - {networkState?.ipv6_addresses && ( - -
-
-

- IPv6 Information -

- -
- {networkState?.dhcp_lease?.ip && ( -
- - Link-local - - - {networkState?.ipv6_link_local} - -
- )} -
- -
- {networkState?.ipv6_addresses && - networkState?.ipv6_addresses.length > 0 && ( -
-

IPv6 Addresses

- {networkState.ipv6_addresses.map(addr => ( -
-
-
- - Address - - - {addr.address} - -
- - {addr.valid_lifetime && ( -
- - Valid Lifetime - - - {addr.valid_lifetime === "" ? ( - - N/A - - ) : ( - - )} - -
- )} - {addr.preferred_lifetime && ( -
- - Preferred Lifetime - - - {addr.preferred_lifetime === "" ? ( - - N/A - - ) : ( - - )} - -
- )} -
-
- ))} -
- )} -
-
-
-
- )} -
-
- - handleLldpModeChange(e.target.value)} - options={filterUnknown([ - { value: "disabled", label: "Disabled" }, - { value: "basic", label: "Basic" }, - { value: "all", label: "All" }, - ])} - /> - -
-
+
+ setShowRenewLeaseConfirm(false)} + 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." + variant="danger" + confirmText="Renew Lease" + onConfirm={() => { + handleRenewLease(); + setShowRenewLeaseConfirm(false); + }} + /> + ); }