/* * Copyright (C) 2021 Red Hat, Inc. * SPDX-License-Identifier: LGPL-2.1-or-later */ import cockpit from "cockpit"; import React, { useState, useContext } from "react"; import { Button } from "@patternfly/react-core/dist/esm/components/Button/index.js"; import { Card, CardHeader, CardTitle } from '@patternfly/react-core/dist/esm/components/Card/index.js'; import { Dropdown, DropdownItem, DropdownList } from '@patternfly/react-core/dist/esm/components/Dropdown/index.js'; import { MenuToggle } from "@patternfly/react-core/dist/esm/components/MenuToggle"; import { Switch } from "@patternfly/react-core/dist/esm/components/Switch/index.js"; import { MinusIcon } from '@patternfly/react-icons'; import { ListingTable } from "cockpit-components-table.jsx"; import { ModelContext } from './model-context.jsx'; import { useEvent } from "hooks"; import { connection_settings, device_state_text, free_member_connection, is_interesting_interface, set_member, show_unexpected_error, syn_click, with_checkpoint, is_managed, } from './interfaces.js'; import { fmt_to_fragments } from 'utils.jsx'; const _ = cockpit.gettext; export const NetworkInterfaceMembers = ({ members, memberIfaces, interfaces, iface, usage_monitor, privileged }) => { const model = useContext(ModelContext); const [isOpen, setIsOpen] = useState(false); useEvent(usage_monitor.grid, "notify"); function renderMemberRows() { const rows = []; members.forEach(iface => { const member_con = iface.MainConnection; const dev = iface.Device; const isActive = (dev && dev.State === 100 && dev.Carrier === true); const onoff = ( { if (val) { with_checkpoint( model, () => member_con.activate(dev).catch(show_unexpected_error), { devices: dev ? [dev] : [], fail_text: fmt_to_fragments(_("Switching on $0 will break the connection to the server, and will make the administration UI unavailable."), {iface.Name}), anyway_text: cockpit.format(_("Switch on $0"), iface.Name) }); } else if (dev) { with_checkpoint( model, () => dev.disconnect().catch(show_unexpected_error), { devices: [dev], fail_text: fmt_to_fragments(_("Switching off $0 will break the connection to the server, and will make the administration UI unavailable."), {iface.Name}), anyway_text: cockpit.format(_("Switch off $0"), iface.Name) }); } } } /> ); const row = ({ columns: [ { title: (!dev || is_managed(dev)) ? : iface.Name }, // Will add traffic info right after { title: (
{onoff} {privileged &&
), props: { className: "pf-v6-c-table__action" } }, ], props: { key: iface.Name, "data-interface": encodeURIComponent(iface.Name), "data-sample-id": isActive ? encodeURIComponent(iface.Name) : null, "data-row-id": iface.Name, } }); if (isActive) { const samples = usage_monitor.samples[iface.Name]; row.columns.splice(1, 0, { title: samples ? cockpit.format_bits_per_sec(samples[1][0] * 8) : "" }); row.columns.splice(2, 0, { title: samples ? cockpit.format_bits_per_sec(samples[0][0] * 8) : "" }); } else { row.columns.splice(1, 0, { title: device_state_text(dev) }); row.columns.splice(1, 0, { title: "" }); } rows.push(row); }); return rows; } const main_connection = iface.MainConnection; const cs = iface.MainConnection && connection_settings(iface.MainConnection); const dropdownItems = []; interfaces.forEach(i => { if (is_interesting_interface(i) && !memberIfaces[i.Name] && i !== iface) { const onClick = () => { with_checkpoint( model, () => { return set_member(model, main_connection, main_connection.Settings, cs.type, i.Name, true) .catch(show_unexpected_error); }, { devices: i.Device ? [i.Device] : [], fail_text: fmt_to_fragments(_("Adding $0 will break the connection to the server, and will make the administration UI unavailable."), {i.Name}), anyway_text: cockpit.format(_("Add $0"), i.Name), hack_does_add_or_remove: true } ); }; dropdownItems.push( {i.Name} ); } }); // We want to show a Tooltip but that isn't supported by PatternFly. // https://github.com/patternfly/patternfly-react/issues/12500 if (dropdownItems.length === 0) { dropdownItems.push( {_("No interfaces available")} ); } const add_btn = ( setIsOpen(false)} toggle={(toggleRef) => ( setIsOpen(!isOpen)}> {_("Add member")} )} isOpen={isOpen} popperProps={{ position: "right" }} > {dropdownItems} ); return ( {_("Interface members")} ); };