diff --git a/src/pages/hosts/NetworkHostDetailsPage.tsx b/src/pages/hosts/NetworkHostDetailsPage.tsx
index 3db8fffb..7f1d5bdb 100644
--- a/src/pages/hosts/NetworkHostDetailsPage.tsx
+++ b/src/pages/hosts/NetworkHostDetailsPage.tsx
@@ -167,6 +167,40 @@ export default function NetworkHostDetailsPage(props: PageProps) {
[hostId, node, networkId, notify, storeDeleteNode, navigate]
);
+ const onHostToggleConnectivity = useCallback(
+ async (newStatus: boolean) => {
+ try {
+ if (!hostId || !node || !networkId) {
+ throw new Error('Host or network not found');
+ }
+ const updatedNode = (await NodesService.updateNode(node.id, networkId, { ...node, connected: newStatus })).data;
+ store.updateNode(node.id, updatedNode);
+ notify.success({
+ message: `Successfully ${newStatus ? 'connected' : 'disconnected'}`,
+ description: `Host is now ${newStatus ? 'connected to' : 'disconnected from'} network ${networkId}.`,
+ });
+ } catch (err) {
+ notify.error({
+ message: `Failed to ${newStatus ? 'connect' : 'disconnect'} host ${newStatus ? 'to' : 'from'} network`,
+ description: extractErrorMsg(err as any),
+ });
+ }
+ },
+ [hostId, node, networkId, notify, store]
+ );
+
+ const promptConfirmDisconnect = () => {
+ Modal.confirm({
+ title: `Do you want to ${node?.connected ? 'disconnect' : 'connect'} host ${host?.name} ${
+ node?.connected ? 'from' : 'to'
+ } network ${networkId}?`,
+ icon: ,
+ onOk() {
+ onHostToggleConnectivity(!node?.connected);
+ },
+ });
+ };
+
const promptConfirmRemove = () => {
let forceDelete = false;
@@ -626,6 +660,18 @@ export default function NetworkHostDetailsPage(props: PageProps) {
navigate(getHostRoute(hostId ?? ''));
},
},
+ {
+ key: 'disconnect',
+ label: (
+
+ {node?.connected ? 'Disconnect from' : 'Connect to'} network
+
+ ),
+ onClick: (ev) => {
+ ev.domEvent.stopPropagation();
+ promptConfirmDisconnect();
+ },
+ },
{
key: 'remove',
label: Remove from network,
diff --git a/src/pages/networks/NetworkDetailsPage.tsx b/src/pages/networks/NetworkDetailsPage.tsx
index f94efc31..c5d01c79 100644
--- a/src/pages/networks/NetworkDetailsPage.tsx
+++ b/src/pages/networks/NetworkDetailsPage.tsx
@@ -60,6 +60,7 @@ import {
TableColumnProps,
Tabs,
TabsProps,
+ Tag,
theme,
Tooltip,
Typography,
@@ -1393,12 +1394,12 @@ export default function NetworkDetailsPage(props: PageProps) {
[networkNodes, store.hostsCommonDetails]
);
- const disconnectNodeFromNetwork = useCallback(
+ const removeNodeFromNetwork = useCallback(
(newStatus: boolean, node: ExtendedNode) => {
let forceDelete = false;
Modal.confirm({
- title: 'Disconnect host from network',
+ title: 'Remove host from network',
content: (
<>
@@ -1450,6 +1451,46 @@ export default function NetworkDetailsPage(props: PageProps) {
[networkId, notify, storeDeleteNode]
);
+ const disconnectNodeFromNetwork = useCallback(
+ (newStatus: boolean, node: ExtendedNode) => {
+ Modal.confirm({
+ title: newStatus ? 'Connect host to network' : 'Disconnect host from network',
+ content: (
+ <>
+
+
+
+ Are you sure you want {node?.name ?? ''} to {newStatus ? 'connect to' : 'disconnect from'} the
+ network?
+
+
+
+ >
+ ),
+ async onOk() {
+ try {
+ if (!networkId) return;
+ const updatedNode = (await NodesService.updateNode(node.id, networkId, { ...node, connected: newStatus }))
+ .data;
+ store.updateNode(node.id, updatedNode);
+ notify.success({
+ message: `Successfully ${newStatus ? 'connected' : 'disconnected'}`,
+ description: `${node?.name ?? 'Host'} is now ${
+ newStatus ? 'connected to' : 'disconnected from'
+ } network ${networkId}.`,
+ });
+ } catch (err) {
+ notify.error({
+ message: 'Failed to update host',
+ description: extractErrorMsg(err as any),
+ });
+ }
+ },
+ });
+ },
+ [networkId, notify, store]
+ );
+
// ui components
const getOverviewContent = useCallback(() => {
if (!network) return ;
@@ -1630,6 +1671,12 @@ export default function NetworkDetailsPage(props: PageProps) {
// title: 'Preferred DNS',
// dataIndex: 'name',
// },
+ {
+ title: 'Connectivity',
+ render: (_, node) => (
+ {node.connected ? 'Connected' : 'Disconnected'}
+ ),
+ },
{
title: 'Health Status',
render(_, node) {
@@ -1653,12 +1700,23 @@ export default function NetworkDetailsPage(props: PageProps) {
},
{
key: 'disconnect',
+ label: node.connected ? 'Disconnect host' : 'Connect host',
+ disabled: node.pendingdelete !== false,
+ title: node.pendingdelete !== false ? 'Host is being disconnected from network' : '',
+ onClick: () =>
+ disconnectNodeFromNetwork(
+ !node.connected,
+ getExtendedNode(node, store.hostsCommonDetails)
+ ),
+ },
+ {
+ key: 'remove',
label: 'Remove from network',
danger: true,
disabled: node.pendingdelete !== false,
title: node.pendingdelete !== false ? 'Host is being removed from network' : '',
onClick: () =>
- disconnectNodeFromNetwork(false, getExtendedNode(node, store.hostsCommonDetails)),
+ removeNodeFromNetwork(false, getExtendedNode(node, store.hostsCommonDetails)),
},
],
}}