Started to create rules editor
This commit is contained in:
		@@ -47,6 +47,7 @@ struct ServerConstraints {
 | 
				
			|||||||
    nwfilter_name_size: LenConstraints,
 | 
					    nwfilter_name_size: LenConstraints,
 | 
				
			||||||
    nwfilter_comment_size: LenConstraints,
 | 
					    nwfilter_comment_size: LenConstraints,
 | 
				
			||||||
    nwfilter_priority: SLenConstraints,
 | 
					    nwfilter_priority: SLenConstraints,
 | 
				
			||||||
 | 
					    nwfilter_selectors_count: LenConstraints,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub async fn static_config(local_auth: LocalAuthEnabled) -> impl Responder {
 | 
					pub async fn static_config(local_auth: LocalAuthEnabled) -> impl Responder {
 | 
				
			||||||
@@ -89,6 +90,7 @@ pub async fn static_config(local_auth: LocalAuthEnabled) -> impl Responder {
 | 
				
			|||||||
                min: -1000,
 | 
					                min: -1000,
 | 
				
			||||||
                max: 1000,
 | 
					                max: 1000,
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
 | 
					            nwfilter_selectors_count: LenConstraints { min: 0, max: 1 },
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,6 +25,7 @@ export interface ServerConstraints {
 | 
				
			|||||||
  nwfilter_name_size: LenConstraint;
 | 
					  nwfilter_name_size: LenConstraint;
 | 
				
			||||||
  nwfilter_comment_size: LenConstraint;
 | 
					  nwfilter_comment_size: LenConstraint;
 | 
				
			||||||
  nwfilter_priority: LenConstraint;
 | 
					  nwfilter_priority: LenConstraint;
 | 
				
			||||||
 | 
					  nwfilter_selectors_count: LenConstraint;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface LenConstraint {
 | 
					export interface LenConstraint {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										146
									
								
								virtweb_frontend/src/widgets/forms/NWFilterRules.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								virtweb_frontend/src/widgets/forms/NWFilterRules.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,146 @@
 | 
				
			|||||||
 | 
					import ArrowDownwardIcon from "@mui/icons-material/ArrowDownward";
 | 
				
			||||||
 | 
					import ArrowUpwardIcon from "@mui/icons-material/ArrowUpward";
 | 
				
			||||||
 | 
					import DeleteIcon from "@mui/icons-material/Delete";
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					  Button,
 | 
				
			||||||
 | 
					  Card,
 | 
				
			||||||
 | 
					  CardActions,
 | 
				
			||||||
 | 
					  CardContent,
 | 
				
			||||||
 | 
					  IconButton,
 | 
				
			||||||
 | 
					} from "@mui/material";
 | 
				
			||||||
 | 
					import { NWFilterRule } from "../../api/NWFilterApi";
 | 
				
			||||||
 | 
					import { EditSection } from "./EditSection";
 | 
				
			||||||
 | 
					import { SelectInput } from "./SelectInput";
 | 
				
			||||||
 | 
					import { TextInput } from "./TextInput";
 | 
				
			||||||
 | 
					import { ServerApi } from "../../api/ServerApi";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function NWFilterRules(p: {
 | 
				
			||||||
 | 
					  editable: boolean;
 | 
				
			||||||
 | 
					  rules: NWFilterRule[];
 | 
				
			||||||
 | 
					  onChange?: () => void;
 | 
				
			||||||
 | 
					}): React.ReactElement {
 | 
				
			||||||
 | 
					  const addRule = () => {
 | 
				
			||||||
 | 
					    p.rules.push({
 | 
				
			||||||
 | 
					      action: "drop",
 | 
				
			||||||
 | 
					      direction: "inout",
 | 
				
			||||||
 | 
					      selectors: [],
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    p.onChange?.();
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const swapRules = (f: number, s: number) => {
 | 
				
			||||||
 | 
					    const swap = p.rules[f];
 | 
				
			||||||
 | 
					    p.rules[f] = p.rules[s];
 | 
				
			||||||
 | 
					    p.rules[s] = swap;
 | 
				
			||||||
 | 
					    p.onChange?.();
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const deleteRule = (num: number) => {
 | 
				
			||||||
 | 
					    p.rules.splice(num, 1);
 | 
				
			||||||
 | 
					    p.onChange?.();
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <EditSection title="Rules">
 | 
				
			||||||
 | 
					      {p.rules.map((r, n) => (
 | 
				
			||||||
 | 
					        <NWRuleEdit
 | 
				
			||||||
 | 
					          key={n}
 | 
				
			||||||
 | 
					          rule={r}
 | 
				
			||||||
 | 
					          onDelete={() => {
 | 
				
			||||||
 | 
					            deleteRule(n);
 | 
				
			||||||
 | 
					          }}
 | 
				
			||||||
 | 
					          onGoDown={
 | 
				
			||||||
 | 
					            n < p.rules.length - 1 ? () => swapRules(n, n + 1) : undefined
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          onGoUp={n > 0 ? () => swapRules(n, n - 1) : undefined}
 | 
				
			||||||
 | 
					          {...p}
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					      ))}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      <div style={{ textAlign: "right" }}>
 | 
				
			||||||
 | 
					        {p.editable && <Button onClick={addRule}>Add a new rule</Button>}
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </EditSection>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function NWRuleEdit(p: {
 | 
				
			||||||
 | 
					  editable: boolean;
 | 
				
			||||||
 | 
					  rule: NWFilterRule;
 | 
				
			||||||
 | 
					  onChange?: () => void;
 | 
				
			||||||
 | 
					  onGoUp?: () => void;
 | 
				
			||||||
 | 
					  onGoDown?: () => void;
 | 
				
			||||||
 | 
					  onDelete: () => void;
 | 
				
			||||||
 | 
					}): React.ReactElement {
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <Card style={{ margin: "30px" }} elevation={3}>
 | 
				
			||||||
 | 
					      <CardContent>
 | 
				
			||||||
 | 
					        <div style={{ display: "flex" }}>
 | 
				
			||||||
 | 
					          <SelectInput
 | 
				
			||||||
 | 
					            editable={p.editable}
 | 
				
			||||||
 | 
					            label="Action"
 | 
				
			||||||
 | 
					            value={p.rule.action}
 | 
				
			||||||
 | 
					            onValueChange={(v) => {
 | 
				
			||||||
 | 
					              p.rule.action = v as any;
 | 
				
			||||||
 | 
					              p.onChange?.();
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            options={[
 | 
				
			||||||
 | 
					              { label: "drop", value: "drop" },
 | 
				
			||||||
 | 
					              { label: "reject", value: "reject" },
 | 
				
			||||||
 | 
					              { label: "accept", value: "accept" },
 | 
				
			||||||
 | 
					              { label: "return", value: "return" },
 | 
				
			||||||
 | 
					              { label: "continue", value: "continue" },
 | 
				
			||||||
 | 
					            ]}
 | 
				
			||||||
 | 
					          />
 | 
				
			||||||
 | 
					          <span style={{ width: "20px" }}></span>
 | 
				
			||||||
 | 
					          <SelectInput
 | 
				
			||||||
 | 
					            editable={p.editable}
 | 
				
			||||||
 | 
					            label="Direction"
 | 
				
			||||||
 | 
					            value={p.rule.direction}
 | 
				
			||||||
 | 
					            onValueChange={(v) => {
 | 
				
			||||||
 | 
					              p.rule.direction = v as any;
 | 
				
			||||||
 | 
					              p.onChange?.();
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            options={[
 | 
				
			||||||
 | 
					              { label: "in", value: "in" },
 | 
				
			||||||
 | 
					              { label: "out", value: "out" },
 | 
				
			||||||
 | 
					              { label: "inout", value: "inout" },
 | 
				
			||||||
 | 
					            ]}
 | 
				
			||||||
 | 
					          />
 | 
				
			||||||
 | 
					          <span style={{ width: "20px" }}></span>
 | 
				
			||||||
 | 
					          <TextInput
 | 
				
			||||||
 | 
					            label="Priority"
 | 
				
			||||||
 | 
					            editable={p.editable}
 | 
				
			||||||
 | 
					            value={p.rule.priority?.toString()}
 | 
				
			||||||
 | 
					            type="number"
 | 
				
			||||||
 | 
					            onValueChange={(v) => {
 | 
				
			||||||
 | 
					              p.rule.priority = v && v !== "" ? Number(v) : undefined;
 | 
				
			||||||
 | 
					              p.onChange?.();
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            size={ServerApi.Config.constraints.nwfilter_priority}
 | 
				
			||||||
 | 
					          />
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </CardContent>
 | 
				
			||||||
 | 
					      <CardActions>
 | 
				
			||||||
 | 
					        {p.editable && (
 | 
				
			||||||
 | 
					          <div style={{ display: "flex", width: "100%" }}>
 | 
				
			||||||
 | 
					            <IconButton color="error" onClick={p.onDelete}>
 | 
				
			||||||
 | 
					              <DeleteIcon />
 | 
				
			||||||
 | 
					            </IconButton>
 | 
				
			||||||
 | 
					            <span style={{ flex: 1 }}></span>
 | 
				
			||||||
 | 
					            {p.onGoUp && (
 | 
				
			||||||
 | 
					              <IconButton onClick={p.onGoUp}>
 | 
				
			||||||
 | 
					                <ArrowUpwardIcon />
 | 
				
			||||||
 | 
					              </IconButton>
 | 
				
			||||||
 | 
					            )}
 | 
				
			||||||
 | 
					            {p.onGoDown && (
 | 
				
			||||||
 | 
					              <IconButton onClick={p.onGoDown}>
 | 
				
			||||||
 | 
					                <ArrowDownwardIcon />
 | 
				
			||||||
 | 
					              </IconButton>
 | 
				
			||||||
 | 
					            )}
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        )}
 | 
				
			||||||
 | 
					      </CardActions>
 | 
				
			||||||
 | 
					    </Card>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -17,6 +17,7 @@ import { TextInput } from "../forms/TextInput";
 | 
				
			|||||||
import { ServerApi } from "../../api/ServerApi";
 | 
					import { ServerApi } from "../../api/ServerApi";
 | 
				
			||||||
import { SelectInput } from "../forms/SelectInput";
 | 
					import { SelectInput } from "../forms/SelectInput";
 | 
				
			||||||
import { NWFSelectReferencedFilters } from "../forms/NWFSelectReferencedFilters";
 | 
					import { NWFSelectReferencedFilters } from "../forms/NWFSelectReferencedFilters";
 | 
				
			||||||
 | 
					import { NWFilterRules } from "../forms/NWFilterRules";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface DetailsProps {
 | 
					interface DetailsProps {
 | 
				
			||||||
  nwfilter: NWFilter;
 | 
					  nwfilter: NWFilter;
 | 
				
			||||||
@@ -159,6 +160,18 @@ function NetworkFilterDetailsTabGeneral(
 | 
				
			|||||||
  );
 | 
					  );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function NetworkFilterDetailsTabRules(
 | 
				
			||||||
 | 
					  p: InnerDetailsProps
 | 
				
			||||||
 | 
					): React.ReactElement {
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <NWFilterRules
 | 
				
			||||||
 | 
					      editable={p.editable}
 | 
				
			||||||
 | 
					      rules={p.nwfilter.rules}
 | 
				
			||||||
 | 
					      onChange={p.onChange}
 | 
				
			||||||
 | 
					    />
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function NetworkFilterDetailsTabXML(p: InnerDetailsProps): React.ReactElement {
 | 
					function NetworkFilterDetailsTabXML(p: InnerDetailsProps): React.ReactElement {
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <XMLAsyncWidget
 | 
					    <XMLAsyncWidget
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user