import { Accordion, AccordionDetails, AccordionSummary, Checkbox, Grid, IconButton, Typography, } from "@material-ui/core"; import ExpandMoreIcon from "@material-ui/icons/ExpandMore"; import RefreshIcon from "@material-ui/icons/Refresh"; import { useCallback, useEffect, useState } from "react"; import DataTable from "react-data-table-component"; import { DndProvider, useDrag, useDrop } from "react-dnd"; import { HTML5Backend } from "react-dnd-html5-backend"; import { useParams } from "react-router-dom"; import API from "utils/API"; import { parseValue, replaceValue, setValue } from "utils/ChangeHelper"; import { formatDistance } from "date-fns"; import AddMember from "./components/AddMember"; import AddGroup from "./components/AddGroup"; import DeleteMember from "./components/DeleteMember"; import ManagedIP from "./components/ManagedIP"; import MemberName from "./components/MemberName"; import MemberSettings from "./components/MemberSettings"; import { useTranslation } from "react-i18next"; const MemberItemType = "MEMBER_ITEM"; const DraggableRow = ({ zoneId, row, content, ...other }) => { const [, drag] = useDrag({ type: MemberItemType, item: { zoneId, row }, }); return (
drag(node)} {...other}> {content}
); }; const DropZone = ({ zoneId, moveRow, children }) => { const [, drop] = useDrop({ accept: MemberItemType, canDrop: (item, monitor) => { return item.zoneId !== zoneId; }, drop: (item, monitor) => { if (monitor.canDrop()) { moveRow(item.zoneId, item.row, zoneId); } }, collect: (monitor) => ({ isOver: monitor.isOver(), canDrop: monitor.canDrop(), }), }); return (
drop(node)} > {children}
); }; function NetworkMembers({ network }) { const { nwid } = useParams(); const [members, setMembers] = useState([]); const [groups, setGroups] = useState([]); const [extraGroups, setExtraGroups] = useState([]); const addGroup = useCallback( async (name) => { if (!groups.includes(name) && !groups.includes(name)) { let mutableExtraGroups = [...extraGroups]; mutableExtraGroups.push(name); setExtraGroups(mutableExtraGroups); } }, [groups, extraGroups] ); const fetchData = useCallback(async () => { try { const members = await API.get("network/" + nwid + "/member"); let groupSet = new Set(); members.data.forEach((x) => groupSet.add(x.group)); setGroups([...groupSet]); setMembers(members.data); console.log("Members:", members.data); } catch (err) { console.error(err); } }, [nwid]); useEffect(() => { fetchData(); const timer = setInterval(() => fetchData(), 30000); return () => clearInterval(timer); }, [nwid, fetchData]); const sendReq = async (mid, data) => { const req = await API.post("/network/" + nwid + "/member/" + mid, data); console.log("Action:", req); }; const { t, i18n } = useTranslation(); const handleChange = (member, key1, key2 = null, mode = "text", id = null) => (event) => { const value = parseValue(event, mode, member, key1, key2, id); const updatedMember = replaceValue({ ...member }, key1, key2, value); const index = members.findIndex((item) => { return item["config"]["id"] === member["config"]["id"]; }); let mutableMembers = [...members]; mutableMembers[index] = updatedMember; const groups = new Set(); mutableMembers.forEach((x) => groups.add(x.group)); let mutableExtraGroups = extraGroups.filter((x) => !groups.has(x)); setMembers(mutableMembers); setGroups([...groups]); setExtraGroups(mutableExtraGroups); const data = setValue({}, key1, key2, value); sendReq(member["config"]["id"], data); }; const columns = [ { id: "auth", name: t("authorized"), minWidth: "80px", cell: (row) => ( ), }, { id: "address", name: t("address"), minWidth: "150px", cell: (row) => ( {row.config.address} ), }, { id: "name", name: t("name") + "/" + t("description"), minWidth: "250px", cell: (row) => , }, { id: "ips", name: t("managedIPs"), minWidth: "220px", cell: (row) => , }, { id: "lastSeen", name: t("lastSeen"), minWidth: "100px", cell: (row) => row.online === 1 ? ( {"ONLINE"} ) : row.controllerId === row.config.address ? ( {"CONTROLLER"} ) : row.online === 0 ? ( {row.lastOnline !== 0 ? formatDistance(row.lastOnline, row.clock, { includeSeconds: false, addSuffix: true, }) : "OFFLINE"} ) : ( {"RELAYED"} ), }, { id: "physicalip", name: t("version") + " / " + t("physIp") + " / " + t("latency"), minWidth: "220px", cell: (row) => row.online === 1 ? (

{"v" + row.config.vMajor + "." + row.config.vMinor + "." + row.config.vRev}
{row.physicalAddress + "/" + row.physicalPort}
{"(" + row.latency + " ms)"}

) : ( "" ), }, { id: "delete", name: t("settings"), minWidth: "50px", right: true, cell: (row) => ( <> ), }, ]; const changeMemberGroup = (oldGroup, member, newGroup) => { member.group = newGroup; let mutableMembers = [...members]; const groups = new Set(); mutableMembers.forEach((x) => groups.add(x.group)); // Remove extra group let mutableExtraGroups = extraGroups.filter((x) => !groups.has(x)); setGroups([...groups]); setExtraGroups(mutableExtraGroups); setMembers(mutableMembers); const data = setValue({}, "group", null, newGroup); sendReq(member["config"]["id"], data); }; return ( }> {t("member", { count: members.length })} {groups .concat(extraGroups) .sort() .map((group) => ( }> {group || "Ungrouped"} {members.length ? ( x.group == group), ]} renderRow={(row, content) => ( )} /> ) : ( {t("noDevices")} {nwid}. )} ))} ); } export default NetworkMembers;