mirror of
https://github.com/dec0dOS/zero-ui.git
synced 2025-07-13 08:33:24 -07:00
Merge pull request #41 from snachx/main
feat: add capabilities and tags support. Thanks @snachx
This commit is contained in:
commit
3827fe81a1
8 changed files with 347 additions and 75 deletions
|
@ -62,6 +62,8 @@ async function createNetworkAdditionalData(nwid) {
|
||||||
additionalConfig: {
|
additionalConfig: {
|
||||||
description: "",
|
description: "",
|
||||||
rulesSource: constants.defaultRulesSource,
|
rulesSource: constants.defaultRulesSource,
|
||||||
|
tagsByName: {},
|
||||||
|
capabilitiesByName: {},
|
||||||
},
|
},
|
||||||
members: [],
|
members: [],
|
||||||
};
|
};
|
||||||
|
@ -79,6 +81,12 @@ async function updateNetworkAdditionalData(nwid, data) {
|
||||||
if (data.hasOwnProperty("rulesSource")) {
|
if (data.hasOwnProperty("rulesSource")) {
|
||||||
additionalData.rulesSource = data.rulesSource;
|
additionalData.rulesSource = data.rulesSource;
|
||||||
}
|
}
|
||||||
|
if (data.hasOwnProperty("tagsByName")) {
|
||||||
|
additionalData.tagsByName = data.tagsByName;
|
||||||
|
}
|
||||||
|
if (data.hasOwnProperty("capabilitiesByName")) {
|
||||||
|
additionalData.capabilitiesByName = data.capabilitiesByName;
|
||||||
|
}
|
||||||
|
|
||||||
if (additionalData) {
|
if (additionalData) {
|
||||||
db.get("networks")
|
db.get("networks")
|
||||||
|
|
|
@ -1,30 +1,26 @@
|
||||||
import { useState, useEffect, useCallback } from "react";
|
|
||||||
import { useParams } from "react-router-dom";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Accordion,
|
Accordion,
|
||||||
AccordionSummary,
|
|
||||||
AccordionDetails,
|
AccordionDetails,
|
||||||
|
AccordionSummary,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
Grid,
|
Grid,
|
||||||
Typography,
|
|
||||||
IconButton,
|
IconButton,
|
||||||
|
Typography,
|
||||||
} from "@material-ui/core";
|
} from "@material-ui/core";
|
||||||
import ExpandMoreIcon from "@material-ui/icons/ExpandMore";
|
import ExpandMoreIcon from "@material-ui/icons/ExpandMore";
|
||||||
import RefreshIcon from "@material-ui/icons/Refresh";
|
import RefreshIcon from "@material-ui/icons/Refresh";
|
||||||
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import DataTable from "react-data-table-component";
|
import DataTable from "react-data-table-component";
|
||||||
|
import { useParams } from "react-router-dom";
|
||||||
import MemberName from "./components/MemberName";
|
|
||||||
import ManagedIP from "./components/ManagedIP";
|
|
||||||
import DeleteMember from "./components/DeleteMember";
|
|
||||||
import MemberSettings from "./components/MemberSettings";
|
|
||||||
import AddMember from "./components/AddMember";
|
|
||||||
|
|
||||||
import API from "utils/API";
|
import API from "utils/API";
|
||||||
import { parseValue, replaceValue, setValue } from "utils/ChangeHelper";
|
import { parseValue, replaceValue, setValue } from "utils/ChangeHelper";
|
||||||
|
import AddMember from "./components/AddMember";
|
||||||
|
import DeleteMember from "./components/DeleteMember";
|
||||||
|
import ManagedIP from "./components/ManagedIP";
|
||||||
|
import MemberName from "./components/MemberName";
|
||||||
|
import MemberSettings from "./components/MemberSettings";
|
||||||
|
|
||||||
function NetworkMembers() {
|
function NetworkMembers({ network }) {
|
||||||
const { nwid } = useParams();
|
const { nwid } = useParams();
|
||||||
const [members, setMembers] = useState([]);
|
const [members, setMembers] = useState([]);
|
||||||
|
|
||||||
|
@ -49,27 +45,23 @@ function NetworkMembers() {
|
||||||
console.log("Action:", req);
|
console.log("Action:", req);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleChange = (
|
const handleChange =
|
||||||
member,
|
(member, key1, key2 = null, mode = "text", id = null) =>
|
||||||
key1,
|
(event) => {
|
||||||
key2 = null,
|
const value = parseValue(event, mode, member, key1, key2, id);
|
||||||
mode = "text",
|
|
||||||
id = null
|
|
||||||
) => (event) => {
|
|
||||||
const value = parseValue(event, mode, member, key1, key2, id);
|
|
||||||
|
|
||||||
const updatedMember = replaceValue({ ...member }, key1, key2, value);
|
const updatedMember = replaceValue({ ...member }, key1, key2, value);
|
||||||
|
|
||||||
const index = members.findIndex((item) => {
|
const index = members.findIndex((item) => {
|
||||||
return item["config"]["id"] === member["config"]["id"];
|
return item["config"]["id"] === member["config"]["id"];
|
||||||
});
|
});
|
||||||
let mutableMembers = [...members];
|
let mutableMembers = [...members];
|
||||||
mutableMembers[index] = updatedMember;
|
mutableMembers[index] = updatedMember;
|
||||||
setMembers(mutableMembers);
|
setMembers(mutableMembers);
|
||||||
|
|
||||||
const data = setValue({}, key1, key2, value);
|
const data = setValue({}, key1, key2, value);
|
||||||
sendReq(member["config"]["id"], data);
|
sendReq(member["config"]["id"], data);
|
||||||
};
|
};
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
|
@ -130,7 +122,11 @@ function NetworkMembers() {
|
||||||
right: true,
|
right: true,
|
||||||
cell: (row) => (
|
cell: (row) => (
|
||||||
<>
|
<>
|
||||||
<MemberSettings member={row} handleChange={handleChange} />
|
<MemberSettings
|
||||||
|
member={row}
|
||||||
|
network={network}
|
||||||
|
handleChange={handleChange}
|
||||||
|
/>
|
||||||
<DeleteMember nwid={nwid} mid={row.config.id} callback={fetchData} />
|
<DeleteMember nwid={nwid} mid={row.config.id} callback={fetchData} />
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,16 +1,19 @@
|
||||||
import { useState } from "react";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Checkbox,
|
Checkbox,
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogTitle,
|
|
||||||
DialogContent,
|
DialogContent,
|
||||||
|
DialogTitle,
|
||||||
|
FormControlLabel,
|
||||||
Grid,
|
Grid,
|
||||||
IconButton,
|
IconButton,
|
||||||
|
Paper,
|
||||||
|
Typography,
|
||||||
} from "@material-ui/core";
|
} from "@material-ui/core";
|
||||||
import BuildIcon from "@material-ui/icons/Build";
|
import BuildIcon from "@material-ui/icons/Build";
|
||||||
|
import { useState } from "react";
|
||||||
|
import Tag from "./components/Tag";
|
||||||
|
|
||||||
function MemberSettings({ member, handleChange }) {
|
function MemberSettings({ member, network, handleChange }) {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
const handleClickOpen = () => {
|
const handleClickOpen = () => {
|
||||||
|
@ -55,6 +58,66 @@ function MemberSettings({ member, handleChange }) {
|
||||||
/>
|
/>
|
||||||
<span>Do Not Auto-Assign IPs</span>
|
<span>Do Not Auto-Assign IPs</span>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Typography variant="h5">Capabilities</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Paper style={{ padding: 20 }}>
|
||||||
|
{Object.entries(network["capabilitiesByName"] || []).length ===
|
||||||
|
0
|
||||||
|
? "No capabilities defined"
|
||||||
|
: ""}
|
||||||
|
{Object.entries(network["capabilitiesByName"] || []).map(
|
||||||
|
([capName, capId]) => (
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Checkbox
|
||||||
|
checked={member["config"]["capabilities"].includes(
|
||||||
|
capId
|
||||||
|
)}
|
||||||
|
color="primary"
|
||||||
|
onChange={handleChange(
|
||||||
|
member,
|
||||||
|
"config",
|
||||||
|
"capabilities",
|
||||||
|
"capChange",
|
||||||
|
capId
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
key={"cap-" + capId}
|
||||||
|
label={capName}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</Paper>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Typography variant="h5">Tags</Typography>
|
||||||
|
</Grid>
|
||||||
|
{Object.entries(network["tagsByName"] || []).length === 0 ? (
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Paper style={{ padding: 20 }}>No tags defined</Paper>
|
||||||
|
</Grid>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
{Object.entries(network["tagsByName"] || []).map(
|
||||||
|
([tagName, tagDetail]) => (
|
||||||
|
<Grid item xs={12} sm={6} key={"tag-" + tagName}>
|
||||||
|
<Tag
|
||||||
|
member={member}
|
||||||
|
tagName={tagName}
|
||||||
|
tagDetail={tagDetail}
|
||||||
|
handleChange={handleChange}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</Grid>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -0,0 +1,165 @@
|
||||||
|
import {
|
||||||
|
Checkbox,
|
||||||
|
FormControlLabel,
|
||||||
|
Grid,
|
||||||
|
IconButton,
|
||||||
|
Input,
|
||||||
|
Paper,
|
||||||
|
Select,
|
||||||
|
Typography,
|
||||||
|
} from "@material-ui/core";
|
||||||
|
import DeleteIcon from "@material-ui/icons/Delete";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { useDebounce } from "react-use";
|
||||||
|
|
||||||
|
function Tag({ member, tagName, tagDetail, handleChange }) {
|
||||||
|
const [tagValue, setTagValue] = useState("");
|
||||||
|
const [tagChangedByUser, setTagChangedByUser] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let tagIndex = member["config"]["tags"].findIndex((item) => {
|
||||||
|
return item[0] === tagDetail["id"];
|
||||||
|
});
|
||||||
|
let value = "";
|
||||||
|
if (tagIndex !== -1) {
|
||||||
|
value = member["config"]["tags"][tagIndex][1];
|
||||||
|
}
|
||||||
|
value = value !== false ? value : "";
|
||||||
|
setTagValue(value);
|
||||||
|
}, [member, tagDetail]);
|
||||||
|
|
||||||
|
useDebounce(
|
||||||
|
async () => {
|
||||||
|
if (tagChangedByUser) {
|
||||||
|
let value = tagValue === "" ? "" : parseInt(tagValue);
|
||||||
|
let event = { target: { value: value } };
|
||||||
|
handleChange(
|
||||||
|
member,
|
||||||
|
"config",
|
||||||
|
"tags",
|
||||||
|
"tagChange",
|
||||||
|
tagDetail["id"]
|
||||||
|
)(event);
|
||||||
|
}
|
||||||
|
setTagChangedByUser(false);
|
||||||
|
},
|
||||||
|
500,
|
||||||
|
[tagValue]
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleSelectChange = (event) => {
|
||||||
|
let newValue = event.target.value;
|
||||||
|
setTagChangedByUser(true);
|
||||||
|
setTagValue(newValue);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFlagChange = (value) => (event) => {
|
||||||
|
let newValue;
|
||||||
|
let oldValue;
|
||||||
|
|
||||||
|
if (tagValue === "") {
|
||||||
|
oldValue = 0;
|
||||||
|
} else {
|
||||||
|
oldValue = tagValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.target.checked) {
|
||||||
|
newValue = oldValue + value;
|
||||||
|
} else {
|
||||||
|
newValue = oldValue - value;
|
||||||
|
}
|
||||||
|
setTagChangedByUser(true);
|
||||||
|
setTagValue(newValue);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleInputChange = (event) => {
|
||||||
|
let value = event.target.value;
|
||||||
|
if (/^(|0|[1-9]\d*)$/.test(value)) {
|
||||||
|
value = value === "" ? value : parseInt(value);
|
||||||
|
} else {
|
||||||
|
value = 0;
|
||||||
|
}
|
||||||
|
setTagChangedByUser(true);
|
||||||
|
setTagValue(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const clearTag = (event) => {
|
||||||
|
setTagChangedByUser(true);
|
||||||
|
setTagValue("");
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Paper style={{ padding: 20 }}>
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Typography
|
||||||
|
variant="h5"
|
||||||
|
color={tagValue === "" ? "error" : "primary"}
|
||||||
|
>
|
||||||
|
{tagName}
|
||||||
|
{tagValue === "" ? (
|
||||||
|
""
|
||||||
|
) : (
|
||||||
|
<IconButton aria-label="delete" onClick={clearTag}>
|
||||||
|
<DeleteIcon />
|
||||||
|
</IconButton>
|
||||||
|
)}
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid container>
|
||||||
|
<Grid item xs={6}>
|
||||||
|
<Select
|
||||||
|
native
|
||||||
|
value={tagValue}
|
||||||
|
onChange={handleSelectChange}
|
||||||
|
displayEmpty
|
||||||
|
style={{ minWidth: 100 }}
|
||||||
|
>
|
||||||
|
<option value="">--</option>
|
||||||
|
{Object.entries(tagDetail["enums"]).map(
|
||||||
|
([enumKey, enumValue]) => (
|
||||||
|
<option key={enumKey} value={enumValue}>
|
||||||
|
{enumKey}
|
||||||
|
</option>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
{Object.values(tagDetail["enums"]).length === 0 &&
|
||||||
|
tagValue !== "" ? (
|
||||||
|
<option value={tagValue}>(no enums)</option>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
{Object.values(tagDetail["enums"]).length !== 0 &&
|
||||||
|
!Object.values(tagDetail["enums"]).includes(tagValue) &&
|
||||||
|
tagValue !== "" ? (
|
||||||
|
<option value={tagValue}>(custom)</option>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
</Select>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={6}>
|
||||||
|
<Input value={tagValue} onChange={handleInputChange} />
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
{Object.entries(tagDetail["flags"]).map(([flagKey, flagValue]) => (
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Checkbox
|
||||||
|
checked={(tagValue & flagValue) === flagValue}
|
||||||
|
onChange={handleFlagChange(flagValue)}
|
||||||
|
color="primary"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
key={"flag-" + flagKey}
|
||||||
|
label={flagKey}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Paper>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Tag;
|
|
@ -0,0 +1 @@
|
||||||
|
export { default } from "./Tag";
|
|
@ -1,34 +1,33 @@
|
||||||
import { useState } from "react";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Accordion,
|
Accordion,
|
||||||
AccordionSummary,
|
|
||||||
AccordionDetails,
|
AccordionDetails,
|
||||||
|
AccordionSummary,
|
||||||
Button,
|
Button,
|
||||||
Divider,
|
Divider,
|
||||||
Snackbar,
|
|
||||||
Hidden,
|
|
||||||
Grid,
|
Grid,
|
||||||
|
Hidden,
|
||||||
|
Snackbar,
|
||||||
Typography,
|
Typography,
|
||||||
} from "@material-ui/core";
|
} from "@material-ui/core";
|
||||||
import ExpandMoreIcon from "@material-ui/icons/ExpandMore";
|
import ExpandMoreIcon from "@material-ui/icons/ExpandMore";
|
||||||
|
|
||||||
import CodeMirror from "@uiw/react-codemirror";
|
import CodeMirror from "@uiw/react-codemirror";
|
||||||
import "codemirror/theme/3024-day.css";
|
import "codemirror/theme/3024-day.css";
|
||||||
|
|
||||||
import { compile } from "external/RuleCompiler";
|
import { compile } from "external/RuleCompiler";
|
||||||
|
|
||||||
import debounce from "lodash/debounce";
|
import debounce from "lodash/debounce";
|
||||||
|
import { useState } from "react";
|
||||||
import API from "utils/API";
|
import API from "utils/API";
|
||||||
|
|
||||||
function NetworkRules({ network }) {
|
function NetworkRules({ network, callback }) {
|
||||||
const [editor, setEditor] = useState(null);
|
const [editor, setEditor] = useState(null);
|
||||||
const [flowData, setFlowData] = useState({
|
const [flowData, setFlowData] = useState({
|
||||||
rules: [...network.config.rules],
|
rules: [...network.config.rules],
|
||||||
capabilities: [...network.config.capabilities],
|
capabilities: [...network.config.capabilities],
|
||||||
tags: [...network.config.tags],
|
tags: [...network.config.tags],
|
||||||
});
|
});
|
||||||
|
const [tagCapByNameData, setTagCapByNameData] = useState({
|
||||||
|
tagsByName: network.tagsByName || {},
|
||||||
|
capabilitiesByName: network.capabilitiesByName || {},
|
||||||
|
});
|
||||||
const [errors, setErrors] = useState([]);
|
const [errors, setErrors] = useState([]);
|
||||||
const [snackbarOpen, setSnackbarOpen] = useState(false);
|
const [snackbarOpen, setSnackbarOpen] = useState(false);
|
||||||
|
|
||||||
|
@ -37,12 +36,16 @@ function NetworkRules({ network }) {
|
||||||
const req = await API.post("/network/" + network["config"]["id"], {
|
const req = await API.post("/network/" + network["config"]["id"], {
|
||||||
config: { ...flowData },
|
config: { ...flowData },
|
||||||
rulesSource: editor.getValue(),
|
rulesSource: editor.getValue(),
|
||||||
|
...tagCapByNameData,
|
||||||
});
|
});
|
||||||
console.log("Action", req);
|
console.log("Action", req);
|
||||||
setSnackbarOpen(true);
|
setSnackbarOpen(true);
|
||||||
const timer = setTimeout(() => {
|
const timer = setTimeout(() => {
|
||||||
setSnackbarOpen(false);
|
setSnackbarOpen(false);
|
||||||
}, 1500);
|
}, 1500);
|
||||||
|
|
||||||
|
callback();
|
||||||
|
|
||||||
return () => clearTimeout(timer);
|
return () => clearTimeout(timer);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -51,14 +54,29 @@ function NetworkRules({ network }) {
|
||||||
const src = event.getValue();
|
const src = event.getValue();
|
||||||
setEditor(event);
|
setEditor(event);
|
||||||
let rules = [],
|
let rules = [],
|
||||||
caps = [],
|
caps = {},
|
||||||
tags = [];
|
tags = {};
|
||||||
const res = compile(src, rules, caps, tags);
|
const res = compile(src, rules, caps, tags);
|
||||||
if (!res) {
|
if (!res) {
|
||||||
|
let capabilitiesByName = {};
|
||||||
|
for (var key in caps) {
|
||||||
|
capabilitiesByName[key] = caps[key].id;
|
||||||
|
}
|
||||||
|
|
||||||
|
let tagsByName = { ...tags };
|
||||||
|
for (let key in tags) {
|
||||||
|
tags[key] = { id: tags[key].id, default: tags[key].default };
|
||||||
|
}
|
||||||
|
|
||||||
setFlowData({
|
setFlowData({
|
||||||
rules: [...rules],
|
rules: [...rules],
|
||||||
capabilities: [...caps],
|
capabilities: [...Object.values(caps)],
|
||||||
tags: [...tags],
|
tags: [...Object.values(tags)],
|
||||||
|
});
|
||||||
|
|
||||||
|
setTagCapByNameData({
|
||||||
|
tagsByName: tagsByName,
|
||||||
|
capabilitiesByName: capabilitiesByName,
|
||||||
});
|
});
|
||||||
setErrors([]);
|
setErrors([]);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,18 +1,15 @@
|
||||||
import { useState, useEffect } from "react";
|
import { Grid, Link, Typography } from "@material-ui/core";
|
||||||
import { Link as RouterLink, useParams, useHistory } from "react-router-dom";
|
|
||||||
import { useLocalStorage } from "react-use";
|
|
||||||
|
|
||||||
import { Link, Grid, Typography } from "@material-ui/core";
|
|
||||||
import ArrowBackIcon from "@material-ui/icons/ArrowBack";
|
import ArrowBackIcon from "@material-ui/icons/ArrowBack";
|
||||||
import useStyles from "./Network.styles";
|
|
||||||
|
|
||||||
import NetworkHeader from "components/NetworkHeader";
|
import NetworkHeader from "components/NetworkHeader";
|
||||||
import NetworkSettings from "components/NetworkSettings";
|
import NetworkManagement from "components/NetworkManagement";
|
||||||
import NetworkMembers from "components/NetworkMembers";
|
import NetworkMembers from "components/NetworkMembers";
|
||||||
import NetworkRules from "components/NetworkRules";
|
import NetworkRules from "components/NetworkRules";
|
||||||
import NetworkManagement from "components/NetworkManagement";
|
import NetworkSettings from "components/NetworkSettings";
|
||||||
|
import { useCallback, useEffect, useState } from "react";
|
||||||
|
import { Link as RouterLink, useHistory, useParams } from "react-router-dom";
|
||||||
|
import { useLocalStorage } from "react-use";
|
||||||
import API from "utils/API";
|
import API from "utils/API";
|
||||||
|
import useStyles from "./Network.styles";
|
||||||
|
|
||||||
function Network() {
|
function Network() {
|
||||||
const { nwid } = useParams();
|
const { nwid } = useParams();
|
||||||
|
@ -22,22 +19,23 @@ function Network() {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
useEffect(() => {
|
const fetchData = useCallback(async () => {
|
||||||
async function fetchData() {
|
try {
|
||||||
try {
|
const network = await API.get("network/" + nwid);
|
||||||
const network = await API.get("network/" + nwid);
|
setNetwork(network.data);
|
||||||
setNetwork(network.data);
|
console.log("Current network:", network.data);
|
||||||
console.log("Current network:", network.data);
|
} catch (err) {
|
||||||
} catch (err) {
|
if (err.response.status === 404) {
|
||||||
if (err.response.status === 404) {
|
history.push("/404");
|
||||||
history.push("/404");
|
|
||||||
}
|
|
||||||
console.error(err);
|
|
||||||
}
|
}
|
||||||
|
console.error(err);
|
||||||
}
|
}
|
||||||
fetchData();
|
|
||||||
}, [nwid, history]);
|
}, [nwid, history]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchData();
|
||||||
|
}, [nwid, fetchData]);
|
||||||
|
|
||||||
if (loggedIn) {
|
if (loggedIn) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -52,8 +50,10 @@ function Network() {
|
||||||
<NetworkSettings network={network} setNetwork={setNetwork} />
|
<NetworkSettings network={network} setNetwork={setNetwork} />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<NetworkMembers />
|
<NetworkMembers network={network} />
|
||||||
{network["config"] && <NetworkRules network={network} />}
|
{network["config"] && (
|
||||||
|
<NetworkRules network={network} callback={fetchData} />
|
||||||
|
)}
|
||||||
<NetworkManagement />
|
<NetworkManagement />
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { pull } from "lodash";
|
||||||
|
|
||||||
export function parseValue(
|
export function parseValue(
|
||||||
event,
|
event,
|
||||||
mode = "text",
|
mode = "text",
|
||||||
|
@ -23,6 +25,25 @@ export function parseValue(
|
||||||
}
|
}
|
||||||
} else if (mode === "custom") {
|
} else if (mode === "custom") {
|
||||||
value = data;
|
value = data;
|
||||||
|
} else if (mode === "capChange") {
|
||||||
|
value = data[key1][key2];
|
||||||
|
if (event.target.checked) {
|
||||||
|
value.push(id);
|
||||||
|
} else {
|
||||||
|
pull(value, id);
|
||||||
|
}
|
||||||
|
} else if (mode === "tagChange") {
|
||||||
|
value = data[key1][key2];
|
||||||
|
let tagValue = event.target.value;
|
||||||
|
let tagIndex = value.findIndex((item) => {
|
||||||
|
return item[0] === id;
|
||||||
|
});
|
||||||
|
if (tagIndex !== -1) {
|
||||||
|
value.splice(tagIndex, 1);
|
||||||
|
}
|
||||||
|
if (tagValue !== "") {
|
||||||
|
value.push([id, tagValue]);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
value = event.target.value;
|
value = event.target.value;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue