add: created components for rules visualization

This commit is contained in:
Domingo Dirutigliano
2023-09-24 22:50:42 +02:00
parent 4c4b80fd23
commit d195f2c7cd
8 changed files with 211 additions and 63 deletions

View File

@@ -0,0 +1,23 @@
import { SegmentedControl, SegmentedControlProps } from "@mantine/core";
import { ActionType } from "./utils";
export const ActionTypeSelector = (props:Omit<SegmentedControlProps, "data">) => (
<SegmentedControl
data={[
{
value: ActionType.ACCEPT,
label: 'Accept',
},
{
value: ActionType.REJECT,
label: 'Reject',
},
{
value: ActionType.DROP,
label: 'Drop',
}
]}
{...props}
/>
)

View File

@@ -0,0 +1,20 @@
import { SegmentedControl, SegmentedControlProps } from "@mantine/core";
import { RuleMode } from "./utils";
export const ModeSelector = (props:Omit<SegmentedControlProps, "data">) => (
<SegmentedControl
data={[
{
value: RuleMode.IN,
label: 'IN',
},
{
value: RuleMode.OUT,
label: 'OUT',
}
]}
{...props}
/>
)

View File

@@ -0,0 +1,23 @@
import { SegmentedControl, SegmentedControlProps } from "@mantine/core";
import { Protocol } from "./utils";
export const ProtocolSelector = (props:Omit<SegmentedControlProps, "data">) => (
<SegmentedControl
data={[
{
value: Protocol.TCP,
label: 'TCP',
},
{
value: Protocol.UDP,
label: 'UDP',
},
{
value: Protocol.ANY,
label: 'ANY',
}
]}
{...props}
/>
)

View File

@@ -0,0 +1,48 @@
import { AutocompleteItem, Select, SelectProps } from "@mantine/core";
import React, { useState } from "react";
import { ipInterfacesQuery } from "../js/utils";
const AutoCompleteItem = React.forwardRef<HTMLDivElement, ItemProps>(
({ netint, value, ...props }: ItemProps, ref) => <div ref={ref} {...props}>
( <b>{netint}</b> ) -{">"} <b>{value}</b>
</div>
);
interface ItemProps extends AutocompleteItem {
netint: string;
}
interface InterfaceInputProps extends Omit<SelectProps, "data">{
initialCustomInterfaces?:AutocompleteItem[]
}
export const InterfaceInput = (props:InterfaceInputProps) => {
const { initialCustomInterfaces, ...propeties } = props
const [customIpInterfaces, setCustomIpInterfaces] = useState<AutocompleteItem[]>(initialCustomInterfaces??[]);
const interfacesQuery = ipInterfacesQuery()
const interfaces = (!interfacesQuery.isLoading?
(interfacesQuery.data!.map(item => ({netint:item.name, value:item.addr, label:item.addr})) as AutocompleteItem[]):
[])
return <Select
placeholder="10.1.1.1"
itemComponent={AutoCompleteItem}
data={[...customIpInterfaces, ...interfaces]}
searchable
dropdownPosition="bottom"
maxDropdownHeight={200}
creatable
getCreateLabel={(query) => `+ Use this: ${query}`}
onCreate={(query) => {
const item = { value: query, netint: "CUSTOM", label: query };
setCustomIpInterfaces((current) => [...current, item]);
return item;
}}
style={props.style?{width:"100%", ...props.style}:{width:"100%"}}
{...propeties}
/>
}

View File

@@ -1,8 +1,9 @@
import { AutocompleteItem, Select, Space, Title } from "@mantine/core"
import React, { useEffect, useState } from "react"
import { getipinterfaces } from "../js/utils";
import { ipInterfacesQuery } from "../js/utils";
import PortInput from "./PortInput";
import { UseFormReturnType } from "@mantine/form/lib/types";
import { InterfaceInput } from "./InterfaceInput";
interface ItemProps extends AutocompleteItem {
netint: string;
@@ -15,39 +16,21 @@ const AutoCompleteItem = React.forwardRef<HTMLDivElement, ItemProps>(
);
export default function PortAndInterface({ form, int_name, port_name, label }:{ form:UseFormReturnType<any>, int_name:string, port_name:string, label?:string }) {
export default function PortAndInterface({ form, int_name, port_name, label, orientation }:{ form:UseFormReturnType<any>, int_name:string, port_name:string, label?:string, orientation?:"line"|"column" }) {
const [ipInterfaces, setIpInterfaces] = useState<AutocompleteItem[]>([]);
useEffect(()=>{
getipinterfaces().then(data => {
setIpInterfaces(data.map(item => ({netint:item.name, value:item.addr, label:item.addr})));
})
},[])
return <>
{label?<>
<Title order={6}>{label}</Title>
<Space h="xs" /></> :null}
<div className='center-flex' style={{width:"100%"}}>
<Select
placeholder="10.1.1.1"
itemComponent={AutoCompleteItem}
data={ipInterfaces}
searchable
dropdownPosition="bottom"
maxDropdownHeight={200}
creatable
getCreateLabel={(query) => `+ Use this: ${query}`}
onCreate={(query) => {
const item = { value: query, netint: "CUSTOM", label: query };
setIpInterfaces((current) => [...current, item]);
return item;
}}
<div className={(!orientation || orientation == "line")?'center-flex':"center-flex-row"} style={{width:"100%"}}>
<InterfaceInput
{...form.getInputProps(int_name)}
style={{width:"100%"}}
/>
<Space w="sm" /><span style={{marginTop:"-3px", fontSize:"1.5em"}}>:</span><Space w="sm" />
{(!orientation || orientation == "line")?
<><Space w="sm" /><span style={{marginTop:"-3px", fontSize:"1.5em"}}>:</span><Space w="sm" /></>:
<Space h="md" />}
<PortInput {...form.getInputProps(port_name)} />
</div>
</>

View File

@@ -1,10 +1,22 @@
import { NumberInput, NumberInputProps } from "@mantine/core"
import { Input, NumberInput, NumberInputProps, TextInput, TextInputProps } from "@mantine/core"
import React, { useState } from "react"
interface PortInputProps extends NumberInputProps {
fullWidth?: boolean
}
const valueParse = (raw_value:string, oldValue:string = "") => {
const value = parseInt(raw_value)
if (value > 65535) {
return oldValue
} else if (value < 1) {
return oldValue
}else{
return value.toString()
}
}
const PortInput = React.forwardRef<HTMLInputElement, PortInputProps>( (props, ref) => {
const [oldValue, setOldValue] = useState<string>(props.defaultValue?props.defaultValue.toString():"")
const {fullWidth, ...propeties} = props
@@ -16,15 +28,9 @@ const PortInput = React.forwardRef<HTMLInputElement, PortInputProps>( (props, r
max={props.max?props.min:65535}
style={fullWidth?props.style:{ width: "75px", ...props.style }}
onInput={(e) => {
const value = parseInt((e.target as HTMLInputElement).value)
if (value > 65535) {
(e.target as HTMLInputElement).value = oldValue
} else if (value < 1) {
(e.target as HTMLInputElement).value = oldValue
}else{
(e.target as HTMLInputElement).value = value.toString()
}
setOldValue((e.target as HTMLInputElement).value)
const target = e.target as HTMLInputElement
target.value = target.value?valueParse(target.value, oldValue):""
setOldValue(target.value)
props.onInput?.(e)
}}
ref={ref}
@@ -33,4 +39,43 @@ const PortInput = React.forwardRef<HTMLInputElement, PortInputProps>( (props, r
})
interface PortRangeInputProps extends TextInputProps {
fullWidth?: boolean,
defaultValues?: number[]
}
export const PortRangeInput = React.forwardRef<HTMLInputElement, PortRangeInputProps>( (props, ref) => {
const oldValueStates = [
useState<string>(props.defaultValue?props.defaultValue?.toString().split("-")[0]:""),
useState<string|undefined>(props.defaultValue?.toString().split("-")[1])
]
const {fullWidth, defaultValues, ...propeties} = props
let defaultValuesInt = defaultValues
if (defaultValuesInt?.length == 2 && defaultValuesInt[0] == defaultValuesInt[1]){
defaultValuesInt = [defaultValuesInt[0]]
}
return <TextInput
variant={props.variant?props.variant:"filled"}
placeholder="1000-1337"
style={fullWidth?props.style:{ width: "150px", ...props.style }}
onInput={(e) => {
const target = e.target as HTMLInputElement
const splitted = target.value.split("-")
const parsedValues = [splitted[0], splitted[1]].map((value, index) => {
const res = value?valueParse(value,oldValueStates[index][0]):value
if (res != oldValueStates[index][0]) oldValueStates[index][1](value)
return res
})
target.value = parsedValues.filter((v, i) => (v !== undefined && (i != 0 || v !== ""))).join("-")
props.onInput?.(e)
}}
ref={ref}
defaultValue={defaultValuesInt?defaultValuesInt.map(v => v.toString()).join("-"):props.defaultValue}
{...propeties}
/>
})
export default PortInput