push: code changes x2

This commit is contained in:
Domingo Dirutigliano
2025-02-28 21:14:09 +01:00
parent 6a11dd0d16
commit 8ae533e8f7
31 changed files with 544 additions and 397 deletions

View File

@@ -25,12 +25,7 @@ import { PiWallLight } from "react-icons/pi";
export const Firewall = () => {
const [tooltipAddOpened, setTooltipAddOpened] = useState(false);
const [tooltipRefreshOpened, setTooltipRefreshOpened] = useState(false);
const [tooltipApplyOpened, setTooltipApplyOpened] = useState(false);
const [tooltipSettingsOpened, setTooltipSettingsOpened] = useState(false);
const [currentPolicy, setCurrentPolicy] = useState<ActionType>(ActionType.ACCEPT)
const [tooltipAddRulOpened, setTooltipAddRulOpened] = useState(false)
const queryClient = useQueryClient()
const rules = firewallRulesQuery()
const [state, handlers] = useListState<Rule & {rule_id:string}>([]);
@@ -364,31 +359,22 @@ export const Firewall = () => {
<Space w="xs" />
<Badge size="md" radius="sm" color="green" variant="filled"><FaDirections style={{ marginBottom: -1, marginRight: 4}}/>Rules: {rules.isLoading?0:rules.data?.rules.length}</Badge>
<Space w="md" />
<Tooltip label="Add a new rule" position='bottom' color="blue" opened={tooltipAddOpened}>
<ActionIcon color="blue" onClick={emptyRuleAdd} size="lg" radius="md" variant="filled"
onFocus={() => setTooltipAddOpened(false)} onBlur={() => setTooltipAddOpened(false)}
onMouseEnter={() => setTooltipAddOpened(true)} onMouseLeave={() => setTooltipAddOpened(false)}><BsPlusLg size={18} /></ActionIcon>
<Tooltip label="Add a new rule" position='bottom' color="blue">
<ActionIcon color="blue" onClick={emptyRuleAdd} size="lg" radius="md" variant="filled"><BsPlusLg size={18} /></ActionIcon>
</Tooltip>
<Space w="xs" />
<Tooltip label="Refresh" position='bottom' color="indigo" opened={tooltipRefreshOpened}>
<Tooltip label="Refresh" position='bottom' color="indigo">
<ActionIcon color="indigo" onClick={()=>queryClient.invalidateQueries(["firewall"])} size="lg" radius="md" variant="filled"
loading={rules.isFetching}
onFocus={() => setTooltipRefreshOpened(false)} onBlur={() => setTooltipRefreshOpened(false)}
onMouseEnter={() => setTooltipRefreshOpened(true)} onMouseLeave={() => setTooltipRefreshOpened(false)}><TbReload size={18} /></ActionIcon>
loading={rules.isFetching}><TbReload size={18} /></ActionIcon>
</Tooltip>
<Space w="xs" />
<Tooltip label="Settings" position='bottom' color="cyan" opened={tooltipSettingsOpened}>
<ActionIcon color="cyan" onClick={()=>setSettingsModal(true)} size="lg" radius="md" variant="filled"
onFocus={() => setTooltipSettingsOpened(false)} onBlur={() => setTooltipSettingsOpened(false)}
onMouseEnter={() => setTooltipSettingsOpened(true)} onMouseLeave={() => setTooltipSettingsOpened(false)}><IoSettingsSharp size={18} /></ActionIcon>
<Tooltip label="Settings" position='bottom' color="cyan">
<ActionIcon color="cyan" onClick={()=>setSettingsModal(true)} size="lg" radius="md" variant="filled"><IoSettingsSharp size={18} /></ActionIcon>
</Tooltip>
<Space w="xs" />
<Tooltip label="Apply" position='bottom' color="grape" opened={tooltipApplyOpened}>
<ActionIcon color="grape" onClick={applyChanges} size="lg" radius="md" variant="filled"
onFocus={() => setTooltipApplyOpened(false)} onBlur={() => setTooltipApplyOpened(false)}
onMouseEnter={() => setTooltipApplyOpened(true)} onMouseLeave={() => setTooltipApplyOpened(false)}
disabled={!valuesChanged}
><TiTick size={22} /></ActionIcon>
<Tooltip label="Apply" position='bottom' color="grape">
<ActionIcon color="grape" onClick={applyChanges} size="lg" radius="md" variant="filled" disabled={!valuesChanged}>
<TiTick size={22} /></ActionIcon>
</Tooltip>
</Box>
</Box>
@@ -424,10 +410,9 @@ export const Firewall = () => {
<Space h="xl"/> <Title className='center-flex' style={{textAlign:"center"}} order={3}>No rule found! Add one clicking the "+" buttons</Title>
<Space h="xl" /> <Space h="xl" />
<Box className='center-flex'>
<Tooltip label="Add a new rule" color="blue" opened={tooltipAddRulOpened}>
<ActionIcon color="blue" onClick={emptyRuleAdd} size="xl" radius="md" variant="filled"
onFocus={() => setTooltipAddRulOpened(false)} onBlur={() => setTooltipAddRulOpened(false)}
onMouseEnter={() => setTooltipAddRulOpened(true)} onMouseLeave={() => setTooltipAddRulOpened(false)}><BsPlusLg size="20px" /></ActionIcon>
<Tooltip label="Add a new rule" color="blue">
<ActionIcon color="blue" onClick={emptyRuleAdd} size="xl" radius="md" variant="filled">
<BsPlusLg size="20px" /></ActionIcon>
</Tooltip>
</Box>
</>}

View File

@@ -1,12 +1,12 @@
import { ActionIcon, Box, Code, Grid, LoadingOverlay, Space, Title, Tooltip } from '@mantine/core';
import { Navigate, useNavigate, useParams } from 'react-router-dom';
import { Badge, Divider, Menu } from '@mantine/core';
import { useState } from 'react';
import { useEffect, useState } from 'react';
import { FaFilter, FaPencilAlt, FaPlay, FaStop } from 'react-icons/fa';
import { nfproxy, nfproxyServiceFilterCodeQuery, nfproxyServicePyfiltersQuery, nfproxyServiceQuery, serviceQueryKey } from '../../components/NFProxy/utils';
import { MdDoubleArrow } from "react-icons/md"
import YesNoModal from '../../components/YesNoModal';
import { errorNotify, isMediumScreen, okNotify, regex_ipv4 } from '../../js/utils';
import { errorNotify, isMediumScreen, okNotify, regex_ipv4, socketio } from '../../js/utils';
import { BsTrashFill } from 'react-icons/bs';
import { BiRename } from 'react-icons/bi'
import RenameForm from '../../components/NFProxy/ServiceRow/RenameForm';
@@ -19,6 +19,10 @@ import PyFilterView from '../../components/PyFilterView';
import { TbPlugConnected } from 'react-icons/tb';
import { CodeHighlight } from '@mantine/code-highlight';
import { FaPython } from "react-icons/fa";
import { FiFileText } from "react-icons/fi";
import { ModalLog } from '../../components/ModalLog';
import { useListState } from '@mantine/hooks';
import { ExceptionWarning } from '../../components/NFProxy/ExceptionWarning';
export default function ServiceDetailsNFProxy() {
@@ -31,11 +35,30 @@ export default function ServiceDetailsNFProxy() {
const [editModal, setEditModal] = useState(false)
const [buttonLoading, setButtonLoading] = useState(false)
const queryClient = useQueryClient()
const [tooltipStopOpened, setTooltipStopOpened] = useState(false);
const [tooltipBackOpened, setTooltipBackOpened] = useState(false);
const filterCode = nfproxyServiceFilterCodeQuery(srv??"")
const navigate = useNavigate()
const isMedium = isMediumScreen()
const [openLogModal, setOpenLogModal] = useState(false)
const [logData, logDataSetters] = useListState<string>([]);
useEffect(()=>{
if (srv){
if (openLogModal){
socketio.emit("nfproxy-outstream-join", { service: srv });
socketio.on(`nfproxy-outstream-${srv}`, (data) => {
logDataSetters.append(data)
});
}else{
logDataSetters.setState([])
socketio.emit("nfproxy-outstream-leave", { service: srv });
}
return () => {
logDataSetters.setState([])
socketio.emit("nfproxy-outstream-leave", { service: srv });
}
}
}, [openLogModal, srv])
if (services.isLoading) return <LoadingOverlay visible={true} />
if (!srv || !serviceInfo || filtersList.isError) return <Navigate to="/" replace />
@@ -101,6 +124,8 @@ export default function ServiceDetailsNFProxy() {
</Box>
{isMedium?null:<Space h="md" />}
<Box className='center-flex'>
<ExceptionWarning service_id={srv} />
<Space w="sm" />
<Badge color={status_color} radius="md" size="xl" variant="filled" mr="sm">
{serviceInfo.status}
</Badge>
@@ -115,7 +140,13 @@ export default function ServiceDetailsNFProxy() {
<Divider />
<Menu.Label><b>Danger zone</b></Menu.Label>
<Menu.Item color="red" leftSection={<BsTrashFill size={18} />} onClick={()=>setDeleteModal(true)}>Delete Service</Menu.Item>
</MenuDropDownWithButton>
</MenuDropDownWithButton>
<Space w="md"/>
<Tooltip label="Show logs" zIndex={0} color="cyan">
<ActionIcon color="cyan" size="lg" radius="md" onClick={()=>setOpenLogModal(true)} loading={buttonLoading} variant="filled">
<FiFileText size="20px" />
</ActionIcon>
</Tooltip>
</Box>
</Box>
{isMedium?null:<Space h="md" />}
@@ -133,23 +164,19 @@ export default function ServiceDetailsNFProxy() {
</Box>
{isMedium?null:<Space h="xl" />}
<Box className='center-flex'>
<Tooltip label="Go back" zIndex={0} color="cyan" opened={tooltipBackOpened}>
<Tooltip label="Go back" zIndex={0} color="cyan">
<ActionIcon color="cyan"
onClick={() => navigate("/")} size="xl" radius="md" variant="filled"
aria-describedby="tooltip-back-id"
onFocus={() => setTooltipBackOpened(false)} onBlur={() => setTooltipBackOpened(false)}
onMouseEnter={() => setTooltipBackOpened(true)} onMouseLeave={() => setTooltipBackOpened(false)}>
aria-describedby="tooltip-back-id">
<FaArrowLeft size="25px" />
</ActionIcon>
</Tooltip>
<Space w="md"/>
<Tooltip label="Stop service" zIndex={0} color="red" opened={tooltipStopOpened}>
<Tooltip label="Stop service" zIndex={0} color="red">
<ActionIcon color="red" loading={buttonLoading}
onClick={stopService} size="xl" radius="md" variant="filled"
disabled={serviceInfo.status === "stop"}
aria-describedby="tooltip-stop-id"
onFocus={() => setTooltipStopOpened(false)} onBlur={() => setTooltipStopOpened(false)}
onMouseEnter={() => setTooltipStopOpened(true)} onMouseLeave={() => setTooltipStopOpened(false)}>
aria-describedby="tooltip-stop-id">
<FaStop size="20px" />
</ActionIcon>
</Tooltip>
@@ -177,7 +204,7 @@ export default function ServiceDetailsNFProxy() {
<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>
</>:<>{filtersList.data?.map( (filterInfo) => <PyFilterView filterInfo={filterInfo} />)}</>
</>:<>{filtersList.data?.map( (filterInfo) => <PyFilterView filterInfo={filterInfo} key={filterInfo.name}/>)}</>
}
<YesNoModal
title='Are you sure to delete this service?'
@@ -196,5 +223,11 @@ export default function ServiceDetailsNFProxy() {
onClose={()=>setEditModal(false)}
edit={serviceInfo}
/>
<ModalLog
opened={openLogModal}
close={()=>setOpenLogModal(false)}
title={`Logs for service ${serviceInfo.name}`}
data={logData.join("")}
/>
</>
}

View File

@@ -20,9 +20,6 @@ export default function NFProxy({ children }: { children: any }) {
const [open, setOpen] = useState(false);
const {srv} = useParams()
const queryClient = useQueryClient()
const [tooltipRefreshOpened, setTooltipRefreshOpened] = useState(false);
const [tooltipAddServOpened, setTooltipAddServOpened] = useState(false);
const [tooltipAddOpened, setTooltipAddOpened] = useState(false);
const isMedium = isMediumScreen()
const services = nfproxyServiceQuery()
const fileDialog = useFileDialog({
@@ -116,27 +113,22 @@ export default function NFProxy({ children }: { children: any }) {
{isMedium?null:<Space h="md" />}
<Box className='center-flex' >
{ 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} />
<Tooltip label="Upload a new filter code" position='bottom' color="blue">
<ActionIcon color="blue" size="lg" radius="md" variant="filled" 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)}
onMouseEnter={() => setTooltipAddOpened(true)} onMouseLeave={() => setTooltipAddOpened(false)}><BsPlusLg size={18} /></ActionIcon>
: <Tooltip label="Add a new service" position='bottom' color="blue">
<ActionIcon color="blue" onClick={()=>setOpen(true)} size="lg" radius="md" variant="filled">
<BsPlusLg size={18} />
</ActionIcon>
</Tooltip>
}
<Space w="xs" />
<Tooltip label="Refresh" position='bottom' color="indigo" opened={tooltipRefreshOpened}>
<ActionIcon color="indigo" onClick={()=>queryClient.invalidateQueries(["nfproxy"])} size="lg" radius="md" variant="filled"
loading={services.isFetching}
onFocus={() => setTooltipRefreshOpened(false)} onBlur={() => setTooltipRefreshOpened(false)}
onMouseEnter={() => setTooltipRefreshOpened(true)} onMouseLeave={() => setTooltipRefreshOpened(false)}><TbReload size={18} /></ActionIcon>
<Tooltip label="Refresh" position='bottom' color="indigo">
<ActionIcon color="indigo" onClick={()=>queryClient.invalidateQueries(["nfproxy"])} size="lg" radius="md" variant="filled" loading={services.isFetching}>
<TbReload size={18} />
</ActionIcon>
</Tooltip>
</Box>
</Box>
@@ -148,10 +140,10 @@ export default function NFProxy({ children }: { children: any }) {
navigator("/nfproxy/"+srv.service_id)
}} />):<><Space h="xl"/> <Title className='center-flex' style={{textAlign:"center"}} order={3}>No services found! Add one clicking the "+" buttons</Title>
<Box className='center-flex'>
<Tooltip label="Add a new service" color="blue" opened={tooltipAddServOpened}>
<ActionIcon color="blue" onClick={()=>setOpen(true)} size="xl" radius="md" variant="filled"
onFocus={() => setTooltipAddServOpened(false)} onBlur={() => setTooltipAddServOpened(false)}
onMouseEnter={() => setTooltipAddServOpened(true)} onMouseLeave={() => setTooltipAddServOpened(false)}><BsPlusLg size="20px" /></ActionIcon>
<Tooltip label="Add a new service" color="blue">
<ActionIcon color="blue" onClick={()=>setOpen(true)} size="xl" radius="md" variant="filled">
<BsPlusLg size="20px" />
</ActionIcon>
</Tooltip>
</Box>
</>}

View File

@@ -27,15 +27,12 @@ export default function ServiceDetailsNFRegex() {
const [open, setOpen] = useState(false)
const services = nfregexServiceQuery()
const serviceInfo = services.data?.find(s => s.service_id == srv)
const [tooltipAddRegexOpened, setTooltipAddRegexOpened] = useState(false)
const regexesList = nfregexServiceRegexesQuery(srv??"")
const [deleteModal, setDeleteModal] = useState(false)
const [renameModal, setRenameModal] = useState(false)
const [editModal, setEditModal] = useState(false)
const [buttonLoading, setButtonLoading] = useState(false)
const queryClient = useQueryClient()
const [tooltipStopOpened, setTooltipStopOpened] = useState(false);
const [tooltipBackOpened, setTooltipBackOpened] = useState(false);
const navigate = useNavigate()
const isMedium = isMediumScreen()
@@ -133,23 +130,19 @@ export default function ServiceDetailsNFRegex() {
</Box>
{isMedium?null:<Space h="xl" />}
<Box className='center-flex'>
<Tooltip label="Go back" zIndex={0} color="cyan" opened={tooltipBackOpened}>
<Tooltip label="Go back" zIndex={0} color="cyan">
<ActionIcon color="cyan"
onClick={() => navigate("/")} size="xl" radius="md" variant="filled"
aria-describedby="tooltip-back-id"
onFocus={() => setTooltipBackOpened(false)} onBlur={() => setTooltipBackOpened(false)}
onMouseEnter={() => setTooltipBackOpened(true)} onMouseLeave={() => setTooltipBackOpened(false)}>
aria-describedby="tooltip-back-id">
<FaArrowLeft size="25px" />
</ActionIcon>
</Tooltip>
<Space w="md"/>
<Tooltip label="Stop service" zIndex={0} color="red" opened={tooltipStopOpened}>
<Tooltip label="Stop service" zIndex={0} color="red">
<ActionIcon color="red" loading={buttonLoading}
onClick={stopService} size="xl" radius="md" variant="filled"
disabled={serviceInfo.status === "stop"}
aria-describedby="tooltip-stop-id"
onFocus={() => setTooltipStopOpened(false)} onBlur={() => setTooltipStopOpened(false)}
onMouseEnter={() => setTooltipStopOpened(true)} onMouseLeave={() => setTooltipStopOpened(false)}>
aria-describedby="tooltip-stop-id">
<FaStop size="20px" />
</ActionIcon>
</Tooltip>
@@ -168,11 +161,9 @@ export default function ServiceDetailsNFRegex() {
<Title className='center-flex' style={{textAlign:"center"}} order={3}>No regex found for this service! Add one by clicking the "+" buttons</Title>
<Space h="xl" /> <Space h="xl" />
<Box className='center-flex'>
<Tooltip label="Add a new regex" zIndex={0} color="blue" opened={tooltipAddRegexOpened}>
<Tooltip label="Add a new regex" zIndex={0} color="blue">
<ActionIcon color="blue" onClick={()=>setOpen(true)} size="xl" radius="md" variant="filled"
aria-describedby="tooltip-AddRegex-id"
onFocus={() => setTooltipAddRegexOpened(false)} onBlur={() => setTooltipAddRegexOpened(false)}
onMouseEnter={() => setTooltipAddRegexOpened(true)} onMouseLeave={() => setTooltipAddRegexOpened(false)}><BsPlusLg size="20px" /></ActionIcon>
aria-describedby="tooltip-AddRegex-id"><BsPlusLg size="20px" /></ActionIcon>
</Tooltip>
</Box>
</>:

View File

@@ -19,9 +19,6 @@ function NFRegex({ children }: { children: any }) {
const [open, setOpen] = useState(false);
const {srv} = useParams()
const queryClient = useQueryClient()
const [tooltipRefreshOpened, setTooltipRefreshOpened] = useState(false);
const [tooltipAddServOpened, setTooltipAddServOpened] = useState(false);
const [tooltipAddOpened, setTooltipAddOpened] = useState(false);
const isMedium = isMediumScreen()
const services = nfregexServiceQuery()
@@ -50,23 +47,17 @@ function NFRegex({ children }: { children: any }) {
{isMedium?null:<Space h="md" />}
<Box className='center-flex' >
{ srv?
<Tooltip label="Add a new regex" position='bottom' color="blue" opened={tooltipAddOpened}>
<ActionIcon color="blue" onClick={()=>setOpen(true)} size="lg" radius="md" variant="filled"
onFocus={() => setTooltipAddOpened(false)} onBlur={() => setTooltipAddOpened(false)}
onMouseEnter={() => setTooltipAddOpened(true)} onMouseLeave={() => setTooltipAddOpened(false)}><BsPlusLg size={18} /></ActionIcon>
<Tooltip label="Add a new regex" position='bottom' color="blue">
<ActionIcon color="blue" onClick={()=>setOpen(true)} size="lg" radius="md" variant="filled"><BsPlusLg 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)}
onMouseEnter={() => setTooltipAddOpened(true)} onMouseLeave={() => setTooltipAddOpened(false)}><BsPlusLg size={18} /></ActionIcon>
: <Tooltip label="Add a new service" position='bottom' color="blue">
<ActionIcon color="blue" onClick={()=>setOpen(true)} size="lg" radius="md" variant="filled"><BsPlusLg size={18} /></ActionIcon>
</Tooltip>
}
<Space w="xs" />
<Tooltip label="Refresh" position='bottom' color="indigo" opened={tooltipRefreshOpened}>
<Tooltip label="Refresh" position='bottom' color="indigo">
<ActionIcon color="indigo" onClick={()=>queryClient.invalidateQueries(["nfregex"])} size="lg" radius="md" variant="filled"
loading={services.isFetching}
onFocus={() => setTooltipRefreshOpened(false)} onBlur={() => setTooltipRefreshOpened(false)}
onMouseEnter={() => setTooltipRefreshOpened(true)} onMouseLeave={() => setTooltipRefreshOpened(false)}><TbReload size={18} /></ActionIcon>
loading={services.isFetching}><TbReload size={18} /></ActionIcon>
</Tooltip>
</Box>
</Box>
@@ -78,10 +69,8 @@ function NFRegex({ children }: { children: any }) {
navigator("/nfregex/"+srv.service_id)
}} />):<><Space h="xl"/> <Title className='center-flex' style={{textAlign:"center"}} order={3}>No services found! Add one clicking the "+" buttons</Title>
<Box className='center-flex'>
<Tooltip label="Add a new service" color="blue" opened={tooltipAddServOpened}>
<ActionIcon color="blue" onClick={()=>setOpen(true)} size="xl" radius="md" variant="filled"
onFocus={() => setTooltipAddServOpened(false)} onBlur={() => setTooltipAddServOpened(false)}
onMouseEnter={() => setTooltipAddServOpened(true)} onMouseLeave={() => setTooltipAddServOpened(false)}><BsPlusLg size="20px" /></ActionIcon>
<Tooltip label="Add a new service" color="blue">
<ActionIcon color="blue" onClick={()=>setOpen(true)} size="xl" radius="md" variant="filled"><BsPlusLg size="20px" /></ActionIcon>
</Tooltip>
</Box>
</>}

View File

@@ -14,10 +14,7 @@ import { GrDirections } from 'react-icons/gr';
function PortHijack() {
const [open, setOpen] = useState(false);
const [tooltipAddServOpened, setTooltipAddServOpened] = useState(false);
const [tooltipAddOpened, setTooltipAddOpened] = useState(false);
const queryClient = useQueryClient()
const [tooltipRefreshOpened, setTooltipRefreshOpened] = useState(false);
const isMedium = isMediumScreen()
const services = porthijackServiceQuery()
@@ -37,17 +34,13 @@ function PortHijack() {
<Box className='center-flex'>
<Badge size="md" radius="sm" color="yellow" variant="filled"><FaServer style={{ marginBottom: -1, marginRight: 4}} />Services: {services.isLoading?0:services.data?.length}</Badge>
<Space w="xs" />
<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)}
onMouseEnter={() => setTooltipAddOpened(true)} onMouseLeave={() => setTooltipAddOpened(false)}><BsPlusLg size={18} /></ActionIcon>
<Tooltip label="Add a new service" position='bottom' color="blue">
<ActionIcon color="blue" onClick={()=>setOpen(true)} size="lg" radius="md" variant="filled"><BsPlusLg size={18} /></ActionIcon>
</Tooltip>
<Space w="xs" />
<Tooltip label="Refresh" position='bottom' color="indigo" opened={tooltipRefreshOpened}>
<Tooltip label="Refresh" position='bottom' color="indigo">
<ActionIcon color="indigo" onClick={()=>queryClient.invalidateQueries(["porthijack"])} size="lg" radius="md" variant="filled"
loading={services.isFetching}
onFocus={() => setTooltipRefreshOpened(false)} onBlur={() => setTooltipRefreshOpened(false)}
onMouseEnter={() => setTooltipRefreshOpened(true)} onMouseLeave={() => setTooltipRefreshOpened(false)}><TbReload size={18} /></ActionIcon>
loading={services.isFetching}><TbReload size={18} /></ActionIcon>
</Tooltip>
</Box>
</Box>
@@ -57,10 +50,8 @@ function PortHijack() {
{(services.data && services.data.length > 0) ?services.data.map( srv => <ServiceRow service={srv} key={srv.service_id} />):<>
<Space h="xl"/> <Title className='center-flex' style={{textAlign:"center"}} order={3}>No services found! Add one clicking the "+" buttons</Title>
<Box className='center-flex'>
<Tooltip label="Add a new service" color="blue" opened={tooltipAddServOpened}>
<ActionIcon color="blue" onClick={()=>setOpen(true)} size="xl" radius="md" variant="filled"
onFocus={() => setTooltipAddServOpened(false)} onBlur={() => setTooltipAddServOpened(false)}
onMouseEnter={() => setTooltipAddServOpened(true)} onMouseLeave={() => setTooltipAddServOpened(false)}><BsPlusLg size="20px" /></ActionIcon>
<Tooltip label="Add a new service" color="blue">
<ActionIcon color="blue" onClick={()=>setOpen(true)} size="xl" radius="md" variant="filled"><BsPlusLg size="20px" /></ActionIcon>
</Tooltip>
</Box>
</>}