Line data Source code
1 : /*
2 : * Copyright (C) 2021 Red Hat, Inc.
3 : * SPDX-License-Identifier: LGPL-2.1-or-later
4 : */
5 :
6 37 : import cockpit from "cockpit";
7 37 : import React, { useState } from 'react';
8 :
9 : import { Flex, FlexItem } from "@patternfly/react-core/dist/esm/layouts/Flex/index.js";
10 : import { Page, } from "@patternfly/react-core/dist/esm/components/Page/index.js";
11 :
12 : import { ListingTableRowProps } from "cockpit-components-table.jsx";
13 :
14 : import {
15 : has_group,
16 : is_loopback,
17 : is_managed,
18 : is_wireless,
19 : render_active_connection,
20 : } from './interfaces.js';
21 : import { Content, ContentVariants, SimpleList, SimpleListGroup, SimpleListItem, Split, SplitItem } from "@patternfly/react-core";
22 : import { NetworkInterfacePage } from "./network-interface.jsx";
23 : import "./anaconda-main.css";
24 :
25 37 : const _ = cockpit.gettext;
26 :
27 : interface AnacondaNetworkPageProps {
28 : privileged: boolean;
29 : operationInProgress: boolean;
30 : usage_monitor: any;
31 : interfaces: any[];
32 : iface?: any;
33 : }
34 :
35 : interface AnacondaActiveNetwork {
36 : isWireless?: boolean;
37 : iface: any;
38 : }
39 :
40 0 : export const AnacondaNetworkPage = ({ privileged, operationInProgress, usage_monitor, interfaces }: AnacondaNetworkPageProps) => {
41 0 : const [active, setActive] = useState<AnacondaActiveNetwork>();
42 : // useEvent(usage_monitor.grid, "notify");
43 :
44 0 : const managedWired: ListingTableRowProps[] = [];
45 0 : const managedWireless: ListingTableRowProps[] = [];
46 0 : let hasDetails = false;
47 :
48 0 : interfaces.forEach(iface => {
49 : // Skip loopback
50 0 : if (is_loopback(iface))
51 0 : return;
52 :
53 : // Skip members
54 0 : else if (has_group(iface))
55 0 : return;
56 :
57 0 : const dev = iface.Device;
58 : // const show_traffic = (dev && (dev.State == 100 || dev.State == 10) && dev.Carrier === true);
59 :
60 : // usage_monitor.add(iface.Name);
61 :
62 0 : const activeConnection = render_active_connection(dev, false, true);
63 0 : const isWireless = is_wireless(iface);
64 :
65 0 : let connectionStatus;
66 0 : if (activeConnection) {
67 0 : connectionStatus = _("Connected")
68 0 : } else {
69 0 : connectionStatus = _("Disconnected")
70 0 : }
71 :
72 0 : const row = (
73 0 : <SimpleListItem key={iface.name} onClick={() => {setActive({isWireless, iface})}}>
74 0 : <Flex
75 0 : direction={{ default: 'row' }}
76 0 : justifyContent={{ default: 'justifyContentSpaceBetween' }}
77 0 : flexWrap={{ default: 'nowrap' }}
78 : >
79 0 : <FlexItem flex={{ default: 'flex_1' }}>{iface.Name}</FlexItem>
80 0 : <FlexItem>
81 0 : <Content component={ContentVariants.small}>{connectionStatus}</Content>
82 0 : </FlexItem>
83 0 : </Flex>
84 0 : </SimpleListItem>
85 : )
86 :
87 : // Details column: show type-specific information
88 : // let detailsColumn = null;
89 : // if (dev?.DeviceType === '802-11-wireless') {
90 : // const networkCount = dev.visibleSsids.length;
91 : // if (networkCount > 0 || dev.ActiveAccessPoint?.Ssid) {
92 : // hasDetails = true;
93 : // detailsColumn = (
94 : // <Flex columnGap={{ default: 'columnGapSm' }}>
95 : // {networkCount > 0 && (
96 : // <FlexItem>
97 : // <Label status="info">
98 : // {cockpit.format(cockpit.ngettext("$0 network", "$0 networks", networkCount), networkCount)}
99 : // </Label>
100 : // </FlexItem>
101 : // )}
102 : // {dev.ActiveAccessPoint?.Ssid && (
103 : // <FlexItem>
104 : // <Label status="success" icon={<ConnectedIcon />}>{dev.ActiveAccessPoint?.Ssid}</Label>
105 : // </FlexItem>
106 : // )}
107 : // </Flex>
108 : // );
109 : // }
110 : // }
111 : // row.columns.push({ title: detailsColumn });
112 :
113 0 : if (!dev || is_managed(dev)) {
114 0 : isWireless ? managedWireless.push(row) : managedWired.push(row);
115 0 : }
116 0 : });
117 :
118 : // TODO: Actions: turn on off action and edit (wired) or join wifi (wireless)
119 0 : const actions = privileged && (
120 0 : <>
121 : {/* <NetworkAction buttonText={_("Add VPN")} type='wg' />
122 : <NetworkAction buttonText={_("Add bond")} type='bond' />
123 : <NetworkAction buttonText={_("Add team")} type='team' />
124 : <NetworkAction buttonText={_("Add bridge")} type='bridge' />
125 : <NetworkAction buttonText={_("Add VLAN")} type='vlan' /> */}
126 0 : </>
127 : );
128 :
129 0 : return (
130 0 : <Page data-test-wait={operationInProgress} id="networking" className="pf-m-no-sidebar anaconda">
131 0 : <Content component="h1">{_("Networks")}</Content>
132 0 : <Split hasGutter>
133 0 : <SplitItem>
134 0 : <SimpleList>
135 0 : {managedWireless.length !== 0 && (
136 0 : <SimpleListGroup title={_("Wireless")} id="wireless-connections">{...managedWireless}</SimpleListGroup>
137 : )}
138 0 : {managedWired.length !== 0 && (
139 0 : <SimpleListGroup title={_("Wired")} id="wired-connections">{...managedWired}</SimpleListGroup>
140 : )}
141 0 : {(managedWireless.length === 0 && managedWired.length === 0) && (
142 0 : <SimpleListItem key="not-found">{_("No networks found")}</SimpleListItem>
143 : )}
144 0 : </SimpleList>
145 0 : </SplitItem>
146 0 : <SplitItem isFilled>
147 0 : {active?.iface &&
148 0 : <NetworkInterfacePage
149 0 : privileged={privileged}
150 0 : operationInProgress={operationInProgress}
151 0 : usage_monitor={usage_monitor}
152 0 : plot_state={undefined}
153 0 : interfaces={interfaces}
154 0 : iface={active.iface} />
155 : }
156 0 : </SplitItem>
157 0 : </Split>
158 :
159 0 : </Page>
160 : );
161 0 : };
162 :
163 : export const AnacondaWirelessDetail = ({active}: {active: AnacondaActiveNetwork}) => {
164 : return <>
165 : <Content component="h2">{_("Wireless")}</Content>
166 : Interface
167 : {active.iface.Name}
168 : Status
169 : Network joined
170 : Security type
171 : </>
172 : }
173 :
174 : export const AnacondaWiredDetail = ({active}: {active: AnacondaActiveNetwork}) => {
175 : return <>
176 : <Content component="h2">{_("Wired")}</Content>
177 : Interface
178 : {active.iface.Name}
179 : Status
180 : IP Settings
181 : </>
182 : }
|