push: code changes
This commit is contained in:
@@ -15,8 +15,21 @@ import { useQueryClient } from '@tanstack/react-query';
|
||||
import NFProxy from './pages/NFProxy';
|
||||
import ServiceDetailsNFProxy from './pages/NFProxy/ServiceDetails';
|
||||
|
||||
|
||||
const socket = IS_DEV?io("ws://"+DEV_IP_BACKEND, {transports: ["websocket"], path:"/sock/socket.io" }):io({transports: ["websocket"], path:"/sock/socket.io"});
|
||||
export const socket = import.meta.env.DEV?
|
||||
io("ws://"+DEV_IP_BACKEND, {
|
||||
path:"/sock/socket.io",
|
||||
transports: ['websocket'],
|
||||
auth: {
|
||||
token: localStorage.getItem("access_token")
|
||||
}
|
||||
}):
|
||||
io({
|
||||
path:"/sock/socket.io",
|
||||
transports: ['websocket'],
|
||||
auth: {
|
||||
token: localStorage.getItem("access_token")
|
||||
}
|
||||
})
|
||||
|
||||
function App() {
|
||||
|
||||
@@ -25,33 +38,20 @@ function App() {
|
||||
const [reqError, setReqError] = useState<undefined|string>()
|
||||
const [error, setError] = useState<string|null>()
|
||||
const [loadinBtn, setLoadingBtn] = useState(false);
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
|
||||
const getStatus = () =>{
|
||||
getstatus().then( res =>{
|
||||
setSystemStatus(res)
|
||||
setReqError(undefined)
|
||||
setLoading(false)
|
||||
}).catch(err=>{
|
||||
setReqError(err.toString())
|
||||
setLoading(false)
|
||||
setTimeout(getStatus, 500)
|
||||
})
|
||||
getstatus().then( res =>{
|
||||
setSystemStatus(res)
|
||||
setReqError(undefined)
|
||||
}).catch(err=>{
|
||||
setReqError(err.toString())
|
||||
setTimeout(getStatus, 500)
|
||||
}).finally( ()=>setLoading(false) )
|
||||
}
|
||||
|
||||
useEffect(()=>{
|
||||
getStatus()
|
||||
socket.on("update", (data) => {
|
||||
queryClient.invalidateQueries({ queryKey: data })
|
||||
})
|
||||
socket.on("connect_error", (err) => {
|
||||
errorNotify("Socket.Io connection failed! ",`Error message: [${err.message}]`)
|
||||
getStatus()
|
||||
});
|
||||
return () => {
|
||||
socket.off("update")
|
||||
socket.off("connect_error")
|
||||
}
|
||||
},[])
|
||||
|
||||
const form = useForm({
|
||||
@@ -145,19 +145,7 @@ function App() {
|
||||
</Notification><Space h="md" /></>:null}
|
||||
</Box>
|
||||
}else if (systemStatus.status === "run" && systemStatus.loggined){
|
||||
return <Routes>
|
||||
<Route element={<MainLayout><Outlet /></MainLayout>}>
|
||||
<Route path="nfregex" element={<NFRegex><Outlet /></NFRegex>} >
|
||||
<Route path=":srv" element={<ServiceDetailsNFRegex />} />
|
||||
</Route>
|
||||
<Route path="nfproxy" element={<NFProxy><Outlet /></NFProxy>} >
|
||||
<Route path=":srv" element={<ServiceDetailsNFProxy />} />
|
||||
</Route>
|
||||
<Route path="firewall" element={<Firewall />} />
|
||||
<Route path="porthijack" element={<PortHijack />} />
|
||||
<Route path="*" element={<HomeRedirector />} />
|
||||
</Route>
|
||||
</Routes>
|
||||
return <PageRouting getStatus={getStatus} />
|
||||
}else{
|
||||
return <Box className='center-flex-row' style={{padding:"100px"}}>
|
||||
<Title order={1} style={{textAlign:"center"}}>Error launching Firegex! 🔥</Title>
|
||||
@@ -167,4 +155,41 @@ function App() {
|
||||
}
|
||||
}
|
||||
|
||||
const PageRouting = ({ getStatus }:{ getStatus:()=>void }) => {
|
||||
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
|
||||
useEffect(()=>{
|
||||
getStatus()
|
||||
socket.on("update", (data) => {
|
||||
queryClient.invalidateQueries({ queryKey: data })
|
||||
})
|
||||
socket.on("connect_error", (err) => {
|
||||
errorNotify("Socket.Io connection failed! ",`Error message: [${err.message}]`)
|
||||
getStatus()
|
||||
});
|
||||
return () => {
|
||||
socket.off("update")
|
||||
socket.off("connect_error")
|
||||
}
|
||||
},[])
|
||||
|
||||
return <Routes>
|
||||
<Route element={<MainLayout><Outlet /></MainLayout>}>
|
||||
<Route path="nfregex" element={<NFRegex><Outlet /></NFRegex>} >
|
||||
<Route path=":srv" element={<ServiceDetailsNFRegex />} />
|
||||
</Route>
|
||||
<Route path="nfproxy" element={<NFProxy><Outlet /></NFProxy>} >
|
||||
<Route path=":srv" element={<ServiceDetailsNFProxy />} />
|
||||
</Route>
|
||||
<Route path="firewall" element={<Firewall />} />
|
||||
<Route path="porthijack" element={<PortHijack />} />
|
||||
<Route path="*" element={<HomeRedirector />} />
|
||||
</Route>
|
||||
</Routes>
|
||||
}
|
||||
|
||||
|
||||
|
||||
export default App;
|
||||
|
||||
@@ -26,7 +26,7 @@ function AddEditService({ opened, onClose, edit }:{ opened:boolean, onClose:()=>
|
||||
validate:{
|
||||
name: (value) => edit? null : value !== "" ? null : "Service name is required",
|
||||
port: (value) => (value>0 && value<65536) ? null : "Invalid port",
|
||||
proto: (value) => ["tcp","udp"].includes(value) ? null : "Invalid protocol",
|
||||
proto: (value) => ["tcp","http"].includes(value) ? null : "Invalid protocol",
|
||||
ip_int: (value) => (value.match(regex_ipv6) || value.match(regex_ipv4)) ? null : "Invalid IP address",
|
||||
}
|
||||
})
|
||||
@@ -50,7 +50,7 @@ function AddEditService({ opened, onClose, edit }:{ opened:boolean, onClose:()=>
|
||||
const submitRequest = ({ name, port, autostart, proto, ip_int, fail_open }:ServiceAddForm) =>{
|
||||
setSubmitLoading(true)
|
||||
if (edit){
|
||||
nfproxy.settings(edit.service_id, { port, proto, ip_int, fail_open }).then( res => {
|
||||
nfproxy.settings(edit.service_id, { port, ip_int, fail_open }).then( res => {
|
||||
if (!res){
|
||||
setSubmitLoading(false)
|
||||
close();
|
||||
@@ -111,13 +111,13 @@ function AddEditService({ opened, onClose, edit }:{ opened:boolean, onClose:()=>
|
||||
/>
|
||||
</Box>
|
||||
<Box className="flex-spacer"></Box>
|
||||
<SegmentedControl
|
||||
{edit?null:<SegmentedControl
|
||||
data={[
|
||||
{ label: 'TCP', value: 'tcp' },
|
||||
{ label: 'UDP', value: 'udp' },
|
||||
{ label: 'HTTP', value: 'http' },
|
||||
]}
|
||||
{...form.getInputProps('proto')}
|
||||
/>
|
||||
/>}
|
||||
</Box>
|
||||
|
||||
<Group justify='flex-end' mt="md" mb="sm">
|
||||
|
||||
54
frontend/src/components/NFProxy/UploadFilterModal.tsx
Normal file
54
frontend/src/components/NFProxy/UploadFilterModal.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
import { Button, FileButton, Group, Modal, Notification, Space } from "@mantine/core";
|
||||
import { nfproxy, Service } from "./utils";
|
||||
import { useEffect, useState } from "react";
|
||||
import { ImCross } from "react-icons/im";
|
||||
import { okNotify } from "../../js/utils";
|
||||
|
||||
export const UploadFilterModal = ({ opened, onClose, service }: { opened: boolean, onClose: () => void, service?: Service }) => {
|
||||
const close = () =>{
|
||||
onClose()
|
||||
setError(null)
|
||||
}
|
||||
|
||||
const [submitLoading, setSubmitLoading] = useState(false)
|
||||
const [error, setError] = useState<string|null>(null)
|
||||
const [file, setFile] = useState<File | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (opened && file){
|
||||
file.bytes().then( code => {
|
||||
console.log(code.toString())
|
||||
setSubmitLoading(true)
|
||||
nfproxy.setpyfilterscode(service?.service_id??"",code.toString()).then( res => {
|
||||
if (!res){
|
||||
setSubmitLoading(false)
|
||||
close();
|
||||
okNotify(`Service ${name} code updated`, `Successfully updated code for service ${name}`)
|
||||
}
|
||||
}).catch( err => {
|
||||
setSubmitLoading(false)
|
||||
setError("Error: "+err)
|
||||
})
|
||||
})
|
||||
}
|
||||
}, [opened, file])
|
||||
|
||||
return <Modal opened={opened && service != null} onClose={onClose} title="Upload filter Code" size="xl" closeOnClickOutside={false} centered>
|
||||
<Space h="md" />
|
||||
<Group justify="center">
|
||||
<FileButton onChange={setFile} accept=".py" multiple={false}>
|
||||
{(props) => <Button {...props}>Upload filter python code</Button>}
|
||||
</FileButton>
|
||||
</Group>
|
||||
|
||||
{error?<>
|
||||
<Space h="md" />
|
||||
<Notification icon={<ImCross size={14} />} color="red" onClose={()=>{setError(null)}}>
|
||||
Error: {error}
|
||||
</Notification>
|
||||
</>:null}
|
||||
<Space h="md" />
|
||||
|
||||
</Modal>
|
||||
|
||||
}
|
||||
@@ -25,7 +25,6 @@ export type ServiceAddForm = {
|
||||
|
||||
export type ServiceSettings = {
|
||||
port?:number,
|
||||
proto?:string,
|
||||
ip_int?:string,
|
||||
fail_open?: boolean,
|
||||
}
|
||||
@@ -55,12 +54,12 @@ export const nfproxy = {
|
||||
serviceinfo: async (service_id:string) => {
|
||||
return await getapi(`nfproxy/services/${service_id}`) as Service;
|
||||
},
|
||||
pyfilterenable: async (regex_id:number) => {
|
||||
const { status } = await postapi(`nfproxy/pyfilters/${regex_id}/enable`) as ServerResponse;
|
||||
pyfilterenable: async (filter_name:string) => {
|
||||
const { status } = await postapi(`nfproxy/pyfilters/${filter_name}/enable`) as ServerResponse;
|
||||
return status === "ok"?undefined:status
|
||||
},
|
||||
pyfilterdisable: async (regex_id:number) => {
|
||||
const { status } = await postapi(`nfproxy/pyfilters/${regex_id}/disable`) as ServerResponse;
|
||||
pyfilterdisable: async (filter_name:string) => {
|
||||
const { status } = await postapi(`nfproxy/pyfilters/${filter_name}/disable`) as ServerResponse;
|
||||
return status === "ok"?undefined:status
|
||||
},
|
||||
servicestart: async (service_id:string) => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Text, Badge, Space, ActionIcon, Tooltip, Box } from '@mantine/core';
|
||||
import { useState } from 'react';
|
||||
import { PyFilter } from '../../js/models';
|
||||
import { errorNotify, okNotify } from '../../js/utils';
|
||||
import { errorNotify, isMediumScreen, okNotify } from '../../js/utils';
|
||||
import { FaPause, FaPlay } from 'react-icons/fa';
|
||||
import { FaFilter } from "react-icons/fa";
|
||||
import { nfproxy } from '../NFProxy/utils';
|
||||
@@ -9,42 +9,39 @@ import { FaPencilAlt } from 'react-icons/fa';
|
||||
|
||||
export default function PyFilterView({ filterInfo }:{ filterInfo:PyFilter }) {
|
||||
|
||||
const [deleteTooltipOpened, setDeleteTooltipOpened] = useState(false);
|
||||
const [statusTooltipOpened, setStatusTooltipOpened] = useState(false);
|
||||
const isMedium = isMediumScreen()
|
||||
|
||||
const changeRegexStatus = () => {
|
||||
(filterInfo.active?nfproxy.pyfilterdisable:nfproxy.pyfilterenable)(filterInfo.filter_id).then(res => {
|
||||
(filterInfo.active?nfproxy.pyfilterdisable:nfproxy.pyfilterenable)(filterInfo.name).then(res => {
|
||||
if(!res){
|
||||
okNotify(`Filter ${filterInfo.name} ${filterInfo.active?"deactivated":"activated"} successfully!`,`Filter with id '${filterInfo.filter_id}' has been ${filterInfo.active?"deactivated":"activated"}!`)
|
||||
okNotify(`Filter ${filterInfo.name} ${filterInfo.active?"deactivated":"activated"} successfully!`,`Filter '${filterInfo.name}' has been ${filterInfo.active?"deactivated":"activated"}!`)
|
||||
}else{
|
||||
errorNotify(`Filter ${filterInfo.name} ${filterInfo.active?"deactivation":"activation"} failed!`,`Error: ${res}`)
|
||||
}
|
||||
}).catch( err => errorNotify(`Filter ${filterInfo.name} ${filterInfo.active?"deactivation":"activation"} failed!`,`Error: ${err}`))
|
||||
}
|
||||
|
||||
return <Box className="firegex__regexview__box">
|
||||
<Box>
|
||||
<Box className='center-flex' style={{width: "100%"}}>
|
||||
<Box className="firegex__regexview__outer_regex_text">
|
||||
<Text className="firegex__regexview__regex_text">{filterInfo.name}</Text>
|
||||
</Box>
|
||||
<Space w="xs" />
|
||||
<Tooltip label={filterInfo.active?"Deactivate":"Activate"} zIndex={0} color={filterInfo.active?"orange":"teal"} opened={statusTooltipOpened}>
|
||||
<ActionIcon color={filterInfo.active?"orange":"teal"} onClick={changeRegexStatus} size="xl" radius="md" variant="filled"
|
||||
onFocus={() => setStatusTooltipOpened(false)} onBlur={() => setStatusTooltipOpened(false)}
|
||||
onMouseEnter={() => setStatusTooltipOpened(true)} onMouseLeave={() => setStatusTooltipOpened(false)}
|
||||
>{filterInfo.active?<FaPause size="20px" />:<FaPlay size="20px" />}</ActionIcon>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
<Box display="flex" mt="sm" ml="xs">
|
||||
<Badge size="md" color="yellow" variant="filled"><FaFilter style={{ marginBottom: -2}} /> {filterInfo.blocked_packets}</Badge>
|
||||
<Space w="xs" />
|
||||
<Badge size="md" color="orange" variant="filled"><FaPencilAlt size={18} /> {filterInfo.edited_packets}</Badge>
|
||||
<Space w="xs" />
|
||||
<Badge size="md" color={filterInfo.active?"lime":"red"} variant="filled">{filterInfo.active?"ACTIVE":"DISABLED"}</Badge>
|
||||
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
return <Box my="sm" display="flex" style={{alignItems:"center"}}>
|
||||
|
||||
<Text className="firegex__regexview__pyfilter_text" style={{ width: "100%", alignItems: "center"}} display="flex" >
|
||||
<Badge size="sm" radius="lg" mr="sm" color={filterInfo.active?"lime":"red"} variant="filled" />
|
||||
{filterInfo.name}
|
||||
<Box className='flex-spacer' />
|
||||
<Space w="xs" />
|
||||
{isMedium?<>
|
||||
<Badge size="md" radius="md" color="yellow" variant="filled"><FaFilter style={{ marginBottom: -2, marginRight: 2}} /> {filterInfo.blocked_packets}</Badge>
|
||||
<Space w="xs" />
|
||||
<Badge size="md" radius="md" color="orange" variant="filled"><FaPencilAlt style={{ marginBottom: -1, marginRight: 2}} /> {filterInfo.edited_packets}</Badge>
|
||||
<Space w="lg" />
|
||||
</>:null}
|
||||
<Tooltip label={filterInfo.active?"Deactivate":"Activate"} zIndex={0} color={filterInfo.active?"orange":"teal"} opened={statusTooltipOpened}>
|
||||
<ActionIcon color={filterInfo.active?"orange":"teal"} onClick={changeRegexStatus} size="lg" radius="md" variant="filled"
|
||||
onFocus={() => setStatusTooltipOpened(false)} onBlur={() => setStatusTooltipOpened(false)}
|
||||
onMouseEnter={() => setStatusTooltipOpened(true)} onMouseLeave={() => setStatusTooltipOpened(false)}
|
||||
>{filterInfo.active?<FaPause size="20px" />:<FaPlay size="20px" />}</ActionIcon>
|
||||
</Tooltip>
|
||||
</Text>
|
||||
|
||||
</Box>
|
||||
}
|
||||
|
||||
@@ -96,6 +96,20 @@ body {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.firegex__regexview__pyfilter_text{
|
||||
padding: 6px;
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
background-color: var(--fourth_color);
|
||||
border: 1px solid #444;
|
||||
overflow-x: hidden;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.firegex__regexview__pyfilter_text:hover{
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.firegex__porthijack__servicerow__row{
|
||||
width: 95%;
|
||||
padding: 15px 0px;
|
||||
|
||||
@@ -51,7 +51,6 @@ export type RegexAddForm = {
|
||||
}
|
||||
|
||||
export type PyFilter = {
|
||||
filter_id:number,
|
||||
name:string,
|
||||
blocked_packets:number,
|
||||
edited_packets:number,
|
||||
|
||||
@@ -72,9 +72,14 @@ export async function genericapi(method:string,path:string,data:any = undefined,
|
||||
const errorDefault = res.statusText
|
||||
return res.json().then( res => reject(getErrorMessageFromServerResponse(res, errorDefault)) ).catch( _err => reject(errorDefault))
|
||||
}
|
||||
res.json().then( res => resolve(res) ).catch( err => reject(err))
|
||||
})
|
||||
.catch(err => {
|
||||
res.text().then(t => {
|
||||
try{
|
||||
resolve(JSON.parse(t))
|
||||
}catch(e){
|
||||
resolve(t)
|
||||
}
|
||||
}).catch( err => reject(err))
|
||||
}).catch(err => {
|
||||
reject(err)
|
||||
})
|
||||
});
|
||||
|
||||
@@ -162,22 +162,22 @@ export default function ServiceDetailsNFProxy() {
|
||||
</Tooltip>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<Divider my="xl" />
|
||||
|
||||
{filterCode.data?<>
|
||||
<Title order={3} style={{textAlign:"center"}} className="center-flex"><FaPython style={{ marginBottom: -3 }} size={30} /><Space w="xs" />Filter code</Title>
|
||||
<CodeHighlight code={filterCode.data} language="python" mt="lg" />
|
||||
</>: null}
|
||||
<Space h="xl" />
|
||||
|
||||
{(!filtersList.data || filtersList.data.length == 0)?<>
|
||||
<Space h="xl" />
|
||||
<Title className='center-flex' style={{textAlign:"center"}} order={3}>No filters found! Edit the proxy file</Title>
|
||||
<Space h="xs" />
|
||||
<Title className='center-flex' style={{textAlign:"center"}} order={3}>Install the firegex client:<Space w="xs" /><Code mb={-4} >pip install fgex</Code></Title>
|
||||
<Space h="xs" />
|
||||
<Title className='center-flex' style={{textAlign:"center"}} order={3}>Then run the command:<Space w="xs" /><Code mb={-4} >fgex nfproxy</Code></Title>
|
||||
</>:
|
||||
<Grid>
|
||||
{filtersList.data?.map( (filterInfo) => <Grid.Col key={filterInfo.filter_id} span={{ lg:6, xs: 12 }}><PyFilterView filterInfo={filterInfo} /></Grid.Col>)}
|
||||
</Grid>
|
||||
</>:<>{filtersList.data?.map( (filterInfo) => <PyFilterView filterInfo={filterInfo} />)}</>
|
||||
}
|
||||
<YesNoModal
|
||||
title='Are you sure to delete this service?'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ActionIcon, Badge, Box, LoadingOverlay, Space, ThemeIcon, Title, Tooltip } from '@mantine/core';
|
||||
import { ActionIcon, Badge, Box, FileButton, LoadingOverlay, Space, ThemeIcon, Title, Tooltip } from '@mantine/core';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { BsPlusLg } from "react-icons/bs";
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
@@ -7,9 +7,11 @@ import { errorNotify, getErrorMessage, isMediumScreen } from '../../js/utils';
|
||||
import AddEditService from '../../components/NFProxy/AddEditService';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import { TbPlugConnected, TbReload } from 'react-icons/tb';
|
||||
import { nfproxyServiceQuery } from '../../components/NFProxy/utils';
|
||||
import { nfproxy, nfproxyServiceQuery } from '../../components/NFProxy/utils';
|
||||
import { FaFilter, FaPencilAlt, FaServer } from 'react-icons/fa';
|
||||
import { VscRegex } from 'react-icons/vsc';
|
||||
import { MdUploadFile } from "react-icons/md";
|
||||
import { notifications } from '@mantine/notifications';
|
||||
import { useFileDialog } from '@mantine/hooks';
|
||||
|
||||
|
||||
export default function NFProxy({ children }: { children: any }) {
|
||||
@@ -23,6 +25,69 @@ export default function NFProxy({ children }: { children: any }) {
|
||||
const [tooltipAddOpened, setTooltipAddOpened] = useState(false);
|
||||
const isMedium = isMediumScreen()
|
||||
const services = nfproxyServiceQuery()
|
||||
const fileDialog = useFileDialog({
|
||||
accept: ".py",
|
||||
multiple: false,
|
||||
resetOnOpen: true,
|
||||
onChange: (files) => {
|
||||
if (files?.length??0 > 0)
|
||||
setFile(files![0])
|
||||
}
|
||||
});
|
||||
const [file, setFile] = useState<File | null>(null);
|
||||
useEffect(() => {
|
||||
if (!srv) return
|
||||
const service = services.data?.find(s => s.service_id === srv)
|
||||
if (!service) return
|
||||
if (file){
|
||||
console.log("Uploading code")
|
||||
const notify_id = notifications.show(
|
||||
{
|
||||
title: "Uploading code",
|
||||
message: `Uploading code for service ${service.name}`,
|
||||
color: "blue",
|
||||
icon: <MdUploadFile size={20} />,
|
||||
autoClose: false,
|
||||
loading: true,
|
||||
}
|
||||
)
|
||||
file.text()
|
||||
.then( code => nfproxy.setpyfilterscode(service?.service_id??"",code.toString()))
|
||||
.then( res => {
|
||||
if (!res){
|
||||
notifications.update({
|
||||
id: notify_id,
|
||||
title: "Code uploaded",
|
||||
message: `Successfully uploaded code for service ${service.name}`,
|
||||
color: "green",
|
||||
icon: <MdUploadFile size={20} />,
|
||||
autoClose: 5000,
|
||||
loading: false,
|
||||
})
|
||||
}else{
|
||||
notifications.update({
|
||||
id: notify_id,
|
||||
title: "Code upload failed",
|
||||
message: `Error: ${res}`,
|
||||
color: "red",
|
||||
icon: <MdUploadFile size={20} />,
|
||||
autoClose: 5000,
|
||||
loading: false,
|
||||
})
|
||||
}
|
||||
}).catch( err => {
|
||||
notifications.update({
|
||||
id: notify_id,
|
||||
title: "Code upload failed",
|
||||
message: `Error: ${err}`,
|
||||
color: "red",
|
||||
icon: <MdUploadFile size={20} />,
|
||||
autoClose: 5000,
|
||||
loading: false,
|
||||
})
|
||||
}).finally(()=>{setFile(null)})
|
||||
}
|
||||
}, [file])
|
||||
|
||||
useEffect(()=> {
|
||||
if(services.isError)
|
||||
@@ -37,7 +102,7 @@ export default function NFProxy({ children }: { children: any }) {
|
||||
<Title order={5} className="center-flex"><ThemeIcon radius="md" size="md" variant='filled' color='lime' ><TbPlugConnected size={20} /></ThemeIcon><Space w="xs" />Netfilter Proxy</Title>
|
||||
{isMedium?<Box className='flex-spacer' />:<Space h="sm" />}
|
||||
<Box className='center-flex' >
|
||||
General stats:
|
||||
{isMedium?"General stats:":null}
|
||||
<Space w="xs" />
|
||||
<Badge size="md" radius="sm" color="green" variant="filled"><FaServer style={{ marginBottom: -1, marginRight: 4}} />Services: {services.isLoading?0:services.data?.length}</Badge>
|
||||
<Space w="xs" />
|
||||
@@ -50,8 +115,16 @@ export default function NFProxy({ children }: { children: any }) {
|
||||
</Box>
|
||||
{isMedium?null:<Space h="md" />}
|
||||
<Box className='center-flex' >
|
||||
{/* Will become the null a button to edit the source code? TODO */}
|
||||
{ srv?null
|
||||
{ srv?
|
||||
<Tooltip label="Upload a new filter code" position='bottom' color="blue" opened={tooltipAddOpened}>
|
||||
<ActionIcon
|
||||
color="blue" size="lg" radius="md" variant="filled"
|
||||
onFocus={() => setTooltipAddOpened(false)} onBlur={() => setTooltipAddOpened(false)}
|
||||
onMouseEnter={() => setTooltipAddOpened(true)}
|
||||
onMouseLeave={() => setTooltipAddOpened(false)} onClick={fileDialog.open}>
|
||||
<MdUploadFile size={18} />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
: <Tooltip label="Add a new service" position='bottom' color="blue" opened={tooltipAddOpened}>
|
||||
<ActionIcon color="blue" onClick={()=>setOpen(true)} size="lg" radius="md" variant="filled"
|
||||
onFocus={() => setTooltipAddOpened(false)} onBlur={() => setTooltipAddOpened(false)}
|
||||
@@ -85,7 +158,9 @@ export default function NFProxy({ children }: { children: any }) {
|
||||
</>}
|
||||
</Box>
|
||||
{srv?children:null}
|
||||
{!srv?<AddEditService opened={open} onClose={closeModal} />:null}
|
||||
{!srv?
|
||||
<AddEditService opened={open} onClose={closeModal} />:null
|
||||
}
|
||||
</>
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ function NFRegex({ children }: { children: any }) {
|
||||
<Title order={5} className="center-flex"><ThemeIcon radius="md" size="md" variant='filled' color='grape' ><BsRegex size={20} /></ThemeIcon><Space w="xs" />Netfilter Regex</Title>
|
||||
{isMedium?<Box className='flex-spacer' />:<Space h="sm" />}
|
||||
<Box className='center-flex' >
|
||||
General stats:
|
||||
{isMedium?"General stats:":null}
|
||||
<Space w="xs" />
|
||||
<Badge size="md" radius="sm" color="green" variant="filled"><FaServer style={{ marginBottom: -1, marginRight: 4}} />Services: {services.isLoading?0:services.data?.length}</Badge>
|
||||
<Space w="xs" />
|
||||
|
||||
Reference in New Issue
Block a user