From e62e655fdc601398fb58027ada166219d4eba8d0 Mon Sep 17 00:00:00 2001 From: DomySh Date: Sun, 12 Jun 2022 12:09:50 +0200 Subject: [PATCH] React Interface v1 --- api-model.txt | 17 +++- frontend/package-lock.json | 81 ++++++++++++++++ frontend/package.json | 1 + frontend/src/App.tsx | 16 +-- frontend/src/components/AddNewRegex.tsx | 82 ++++++++++++++++ frontend/src/components/AddNewService.tsx | 77 +++++++++++++++ frontend/src/components/Header/index.tsx | 54 ++++++++--- frontend/src/components/MainLayout.tsx | 43 +++----- .../RegexView/RegexView.module.scss | 6 ++ frontend/src/components/RegexView/index.tsx | 19 ++++ frontend/src/components/ServiceRow/index.tsx | 8 +- frontend/src/index.scss | 11 +++ frontend/src/index.tsx | 8 -- frontend/src/js/models.ts | 21 +++- frontend/src/js/utils.ts | 47 ++++++++- frontend/src/pages/HomePage.tsx | 38 +++++--- frontend/src/pages/Service.tsx | 11 --- frontend/src/pages/ServiceDetails.tsx | 97 +++++++++++++++++++ frontend/src/reportWebVitals.ts | 15 --- frontend/src/setupTests.ts | 5 - 20 files changed, 547 insertions(+), 110 deletions(-) create mode 100755 frontend/src/components/AddNewRegex.tsx create mode 100755 frontend/src/components/AddNewService.tsx create mode 100755 frontend/src/components/RegexView/RegexView.module.scss create mode 100755 frontend/src/components/RegexView/index.tsx delete mode 100755 frontend/src/pages/Service.tsx create mode 100755 frontend/src/pages/ServiceDetails.tsx delete mode 100755 frontend/src/reportWebVitals.ts delete mode 100755 frontend/src/setupTests.ts diff --git a/api-model.txt b/api-model.txt index 3aba977..4548814 100755 --- a/api-model.txt +++ b/api-model.txt @@ -30,6 +30,18 @@ serv_id = serv_id.lower() } ] +/api/service/ + +{ + "id":"serv_id", + "name":"text", + "status":"stop"/"wait"/"active"/"pause", + "public_port":1234, + "internal_port":44444, + "n_packets":1, + "n_regex":1, +} + /api/service//stop { @@ -63,7 +75,9 @@ serv_id = serv_id.lower() /api/service//regexes [ - "5787":{ + { + "id":5787, + "service_id":"serv_id", "regex":"base64" "is_blacklist":true, "mode":"C","S","B" // C->S S->C BOTH @@ -73,6 +87,7 @@ serv_id = serv_id.lower() /api/regex/ { + "id":5787, "service_id":"serv_id", "regex":"base64" "is_blacklist":true, diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 40b1f0e..5db9ac8 100755 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -22,6 +22,7 @@ "@types/node": "^16.11.39", "@types/react": "^18.0.12", "@types/react-dom": "^18.0.5", + "buffer": "^6.0.3", "react": "^18.1.0", "react-dom": "^18.1.0", "react-icons": "^4.4.0", @@ -5286,6 +5287,25 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", @@ -5458,6 +5478,29 @@ "node-int64": "^0.4.0" } }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -8825,6 +8868,25 @@ "node": ">=4" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/ignore": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", @@ -20686,6 +20748,11 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, "batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", @@ -20822,6 +20889,15 @@ "node-int64": "^0.4.0" } }, + "buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, "buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -23262,6 +23338,11 @@ "harmony-reflect": "^1.4.6" } }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, "ignore": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index 6a0a7e1..389c4c8 100755 --- a/frontend/package.json +++ b/frontend/package.json @@ -17,6 +17,7 @@ "@types/node": "^16.11.39", "@types/react": "^18.0.12", "@types/react-dom": "^18.0.5", + "buffer": "^6.0.3", "react": "^18.1.0", "react-dom": "^18.1.0", "react-icons": "^4.4.0", diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 035383c..c85dc26 100755 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,17 +1,17 @@ import React from 'react'; -import { Navigate, Route, Routes } from 'react-router-dom'; +import { Navigate, Outlet, Route, Routes } from 'react-router-dom'; import MainLayout from './components/MainLayout'; import HomePage from './pages/HomePage'; -import Service from './pages/Service'; +import ServiceDetails from './pages/ServiceDetails'; function App() { - return - - } /> - } /> - } /> + return + }> + } /> + } /> + } /> + - } export default App; diff --git a/frontend/src/components/AddNewRegex.tsx b/frontend/src/components/AddNewRegex.tsx new file mode 100755 index 0000000..d435635 --- /dev/null +++ b/frontend/src/components/AddNewRegex.tsx @@ -0,0 +1,82 @@ +import { Button, Group, NumberInput, Space, TextInput, Notification } from '@mantine/core'; +import { useForm } from '@mantine/hooks'; +import React, { useState } from 'react'; +import { ServiceAddForm } from '../js/models'; +import { addservice } from '../js/utils'; +import { ImCross } from "react-icons/im" + +function AddNewRegex({ closePopup, service }:{ closePopup:()=>void, service:string }) { + + return <> + /* + + const form = useForm({ + initialValues: { + regex:"", + is_blacklist:true, + mode:"B" + }, + validationRules:{ + regex: (value) => value !== ""?true:false, + port: (value) => value>0 && value<65536 + } + }) + + const [submitLoading, setSubmitLoading] = useState(false) + const [error, setError] = useState(null) + + const submitRequest = (values:ServiceAddForm) =>{ + setSubmitLoading(true) + addservice(values).then( res => { + if (!res){ + setSubmitLoading(false) + closePopup(); + }else{ + setSubmitLoading(false) + setError("Invalid request! [ "+res+" ]") + } + }).catch( err => { + setSubmitLoading(false) + setError("Request Failed! [ "+err+" ]") + }) + } + + + return
+ + + + + + + + + + + + + + + {error?<> + } color="red" onClose={()=>{setError(null)}}> + Error: {error} + :null} + + + */ + +} + +export default AddNewRegex; diff --git a/frontend/src/components/AddNewService.tsx b/frontend/src/components/AddNewService.tsx new file mode 100755 index 0000000..b0ea47d --- /dev/null +++ b/frontend/src/components/AddNewService.tsx @@ -0,0 +1,77 @@ +import { Button, Group, NumberInput, Space, TextInput, Notification } from '@mantine/core'; +import { useForm } from '@mantine/hooks'; +import React, { useState } from 'react'; +import { ServiceAddForm } from '../js/models'; +import { addservice } from '../js/utils'; +import { ImCross } from "react-icons/im" + +function AddNewService({ closePopup }:{ closePopup:()=>void }) { + + const form = useForm({ + initialValues: { + name:"", + port:1, + }, + validationRules:{ + name: (value) => value !== ""?true:false, + port: (value) => value>0 && value<65536 + } + }) + + const [submitLoading, setSubmitLoading] = useState(false) + const [error, setError] = useState(null) + + const submitRequest = (values:ServiceAddForm) =>{ + setSubmitLoading(true) + addservice(values).then( res => { + if (!res){ + setSubmitLoading(false) + closePopup(); + }else{ + setSubmitLoading(false) + setError("Invalid request! [ "+res+" ]") + } + }).catch( err => { + setSubmitLoading(false) + setError("Request Failed! [ "+err+" ]") + }) + } + + + return
+ + + + + + + + + + + + + + + {error?<> + } color="red" onClose={()=>{setError(null)}}> + Error: {error} + :null} + + + +} + +export default AddNewService; diff --git a/frontend/src/components/Header/index.tsx b/frontend/src/components/Header/index.tsx index 0f5ab99..f945153 100755 --- a/frontend/src/components/Header/index.tsx +++ b/frontend/src/components/Header/index.tsx @@ -1,11 +1,15 @@ import React, { useEffect, useState } from 'react'; -import { ActionIcon, Badge } from '@mantine/core'; +import { ActionIcon, Badge, Modal } from '@mantine/core'; import style from "./Header.module.scss"; import { generalstats } from '../../js/utils'; -import { GeneralStats, update_freq } from '../../js/models'; +import { GeneralStats, notification_time, update_freq } from '../../js/models'; import { BsPlusLg } from "react-icons/bs" import { AiFillHome } from "react-icons/ai" -import { useLocation, useNavigate } from 'react-router-dom'; +import { useLocation, useNavigate, useParams } from 'react-router-dom'; +import AddNewRegex from '../AddNewRegex'; +import AddNewService from '../AddNewService'; +import { showNotification } from '@mantine/notifications'; +import { ImCross } from 'react-icons/im'; function Header() { @@ -14,17 +18,31 @@ function Header() { const navigator = useNavigate() - const updateInfo = () => { - generalstats().then(res => { - setGeneralStats(res) - setTimeout(updateInfo, update_freq) - }).catch( - err =>{ - setTimeout(updateInfo, update_freq)} - ) + const updateInfo = () => { + generalstats().then(res => { + setGeneralStats(res) + }).catch( + err =>{ + showNotification({ + autoClose: notification_time, + title: "General Info Auto-Update failed!", + message: "[ "+err+" ]", + color: 'red', + icon: , + }); + }) } - useEffect(updateInfo,[]); + useEffect(()=>{ + updateInfo() + const updater = setInterval(updateInfo, update_freq) + return () => { clearInterval(updater) } + }, []); + + + const {srv_id} = useParams() + const [open, setOpen] = useState(false); + const closeModal = () => {setOpen(false);} return
LOGO
@@ -40,7 +58,17 @@ function Header() { :null} - + setOpen(true)} size="xl" radius="md" variant="filled"> + {srv_id? + + + : + + + + } + +
} diff --git a/frontend/src/components/MainLayout.tsx b/frontend/src/components/MainLayout.tsx index 8e6fd26..49d4f6b 100755 --- a/frontend/src/components/MainLayout.tsx +++ b/frontend/src/components/MainLayout.tsx @@ -1,37 +1,22 @@ -import { Container, MantineProvider } from '@mantine/core'; -import React, { useEffect, useState } from 'react'; -import { Service, update_freq } from '../js/models'; -import { servicelist } from '../js/utils'; +import { Container, MantineProvider, Space } from '@mantine/core'; +import { NotificationsProvider } from '@mantine/notifications'; +import React from 'react'; import Footer from './Footer'; import Header from './Header'; function MainLayout({ children }:{ children:any }) { - - const [services, setServices] = useState([]); - - const updateInfo = () => { - servicelist().then(res => { - setServices(res) - setTimeout(updateInfo, update_freq) - }).catch( - err =>{ - setTimeout(updateInfo, update_freq)} - ) - } - - useEffect(updateInfo,[]); - return <> - -
-
- - {children} - -
-
- - + + +
+ + + {children} + + +
+ + } diff --git a/frontend/src/components/RegexView/RegexView.module.scss b/frontend/src/components/RegexView/RegexView.module.scss new file mode 100755 index 0000000..26f5d90 --- /dev/null +++ b/frontend/src/components/RegexView/RegexView.module.scss @@ -0,0 +1,6 @@ + + +.box{ + padding:30px; + margin:5px; +} \ No newline at end of file diff --git a/frontend/src/components/RegexView/index.tsx b/frontend/src/components/RegexView/index.tsx new file mode 100755 index 0000000..c67dabc --- /dev/null +++ b/frontend/src/components/RegexView/index.tsx @@ -0,0 +1,19 @@ +import { TextInput } from '@mantine/core'; +import React from 'react'; +import { RegexFilter } from '../../js/models'; +import { getHumanReadableRegex } from '../../js/utils'; + +import style from "./RegexView.module.scss"; + + +function RegexView({ regexInfo }:{ regexInfo:RegexFilter }) { + return
+ + +
+} + +export default RegexView; diff --git a/frontend/src/components/ServiceRow/index.tsx b/frontend/src/components/ServiceRow/index.tsx index 49b13cc..b265824 100755 --- a/frontend/src/components/ServiceRow/index.tsx +++ b/frontend/src/components/ServiceRow/index.tsx @@ -1,6 +1,6 @@ import { ActionIcon, Badge, Grid, Space, Title } from '@mantine/core'; import React from 'react'; -import { FaPause, FaPlay } from 'react-icons/fa'; +import { FaPause, FaPlay, FaStop } from 'react-icons/fa'; import { Service } from '../../js/models'; import { MdOutlineArrowForwardIos } from "react-icons/md" import style from "./ServiceRow.module.scss"; @@ -19,7 +19,7 @@ function ServiceRow({ service, onClick }:{ service:Service, onClick?:()=>void })
-
{service.name} :{service.public_port}
+
{service.name} :{service.public_port}
{service.internal_port} {"->"} {service.public_port}
@@ -32,7 +32,9 @@ function ServiceRow({ service, onClick }:{ service:Service, onClick?:()=>void })
- + + {service.status === "pause"?:} +
diff --git a/frontend/src/index.scss b/frontend/src/index.scss index 8c32376..8849ce8 100755 --- a/frontend/src/index.scss +++ b/frontend/src/index.scss @@ -21,4 +21,15 @@ body { .flex-spacer{ flex-grow: 1; +} + +::-webkit-scrollbar { + width: 12px; + margin:3px; + background: #333; + cursor: pointer; +} +::-webkit-scrollbar-thumb { + background: #757575; + border-radius: 8px; } \ No newline at end of file diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx index 26b7679..0a41421 100755 --- a/frontend/src/index.tsx +++ b/frontend/src/index.tsx @@ -3,20 +3,12 @@ import ReactDOM from 'react-dom/client'; import { BrowserRouter } from "react-router-dom" import './index.scss'; import App from './App'; -import reportWebVitals from './reportWebVitals'; const root = ReactDOM.createRoot( document.getElementById('root') as HTMLElement ); root.render( - - ); - -// If you want to start measuring performance in your app, pass a function -// to log results (for example: reportWebVitals(console.log)) -// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals -reportWebVitals(); diff --git a/frontend/src/js/models.ts b/frontend/src/js/models.ts index e44c74c..6bfc8c9 100755 --- a/frontend/src/js/models.ts +++ b/frontend/src/js/models.ts @@ -1,6 +1,7 @@ -export const update_freq = 3000; +export const update_freq = 5000; +export const notification_time = 2000; export type GeneralStats = { services:number, @@ -17,3 +18,21 @@ export type Service = { n_packets:number, n_regex:number, } + +export type ServiceAddForm = { + name:string, + port:number +} + + +export type ServerResponse = { + status:string +} + +export type RegexFilter = { + id:number, + service_id:string, + regex:string + is_blacklist:boolean, + mode:string // C->S S->C BOTH +} \ No newline at end of file diff --git a/frontend/src/js/utils.ts b/frontend/src/js/utils.ts index 84cd831..378deca 100755 --- a/frontend/src/js/utils.ts +++ b/frontend/src/js/utils.ts @@ -1,14 +1,55 @@ -import { GeneralStats, Service } from "./models"; +import { GeneralStats, Service, ServiceAddForm, ServerResponse, RegexFilter } from "./models"; export async function getapi(path:string):Promise{ return await fetch(`/api/${path}`).then( res => res.json() ) } +export async function postapi(path:string,data:any):Promise{ + return await fetch(`/api/${path}`, { + method: 'POST', + cache: 'no-cache', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(data) + }).then(res => res.json()); +} -export async function generalstats():Promise{ + +export async function generalstats(){ return await getapi("general-stats") as GeneralStats; } -export async function servicelist():Promise{ +export async function servicelist(){ return await getapi("services") as Service[]; +} + +export async function serviceinfo(service_id:string){ + return await getapi(`service/${service_id}`) as Service; +} + +export async function addservice(data:ServiceAddForm) { + const { status } = await postapi("services/add",data) as ServerResponse; + return status === "ok"?undefined:status +} + +export async function serviceregexlist(service_id:string){ + return await getapi(`service/${service_id}/regexes`) as RegexFilter[]; +} + +const unescapedChars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$&\'()*+,-./:;<=>?@[\\]^_`{|}~ "; + +export function getHumanReadableRegex(regexB64:string){ + var Buffer = require('buffer').Buffer + const regex = Buffer.from(regexB64, "base64") + let res = "" + for (let i=0; i < regex.length; i++){ + const byte = String.fromCharCode(regex[i]); + if (unescapedChars.includes(byte)){ + res+=byte + }else{ + res+="%"+regex[i].toString(16) + } + } + return res } \ No newline at end of file diff --git a/frontend/src/pages/HomePage.tsx b/frontend/src/pages/HomePage.tsx index 6192e8a..c28fe6a 100755 --- a/frontend/src/pages/HomePage.tsx +++ b/frontend/src/pages/HomePage.tsx @@ -1,8 +1,11 @@ +import { Space, Title } from '@mantine/core'; +import { showNotification } from '@mantine/notifications'; import React, { useEffect, useState } from 'react'; -import { Navigate, useNavigate, useRoutes } from 'react-router-dom'; +import { useNavigate } from 'react-router-dom'; import ServiceRow from '../components/ServiceRow'; -import { Service, update_freq } from '../js/models'; +import { notification_time, Service, update_freq } from '../js/models'; import { servicelist } from '../js/utils'; +import { ImCross } from "react-icons/im" function HomePage() { @@ -30,21 +33,30 @@ function HomePage() { const navigator = useNavigate() const updateInfo = () => { - servicelist().then(res => { - setServices(res) - setTimeout(updateInfo, update_freq) - }).catch( - err =>{ - setTimeout(updateInfo, update_freq)} - ) + servicelist().then(res => { + setServices(res) + }).catch( + err =>{ + showNotification({ + autoClose: notification_time, + title: "Home Page Auto-Update failed!", + message: "[ "+err+" ]", + color: 'red', + icon: , + }); + }) } - useEffect(updateInfo,[]); - + useEffect(()=>{ + updateInfo() + const updater = setInterval(updateInfo, update_freq) + return () => { clearInterval(updater) } + }, []); + return
- {services.map( srv => { + {services.length > 0?services.map( srv => { navigator("/"+srv.id) - }} />)} + }} />):<> No services found! Add one clicking the button above}
} diff --git a/frontend/src/pages/Service.tsx b/frontend/src/pages/Service.tsx deleted file mode 100755 index 677fe6a..0000000 --- a/frontend/src/pages/Service.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react'; -import { useParams } from 'react-router-dom'; - -function Service() { - const {srv_id} = useParams() - return
- Service: {srv_id} -
-} - -export default Service; diff --git a/frontend/src/pages/ServiceDetails.tsx b/frontend/src/pages/ServiceDetails.tsx new file mode 100755 index 0000000..a5dfba0 --- /dev/null +++ b/frontend/src/pages/ServiceDetails.tsx @@ -0,0 +1,97 @@ +import { Grid, Space, Title } from '@mantine/core'; +import { showNotification } from '@mantine/notifications'; +import React, { useEffect, useState } from 'react'; +import { ImCross } from 'react-icons/im'; +import { useParams } from 'react-router-dom'; +import RegexView from '../components/RegexView'; +import ServiceRow from '../components/ServiceRow'; +import { notification_time, RegexFilter, Service, update_freq } from '../js/models'; +import { serviceinfo, serviceregexlist } from '../js/utils'; + +function ServiceDetails() { + const {srv_id} = useParams() + + const [serviceInfo, setServiceInfo] = useState({ + id:srv_id?srv_id:"", + internal_port:0, + n_packets:0, + n_regex:0, + name:srv_id?srv_id:"", + public_port:0, + status:"🤔" + }) + + const [regexesList, setRegexesList] = useState([ + { + id:3546, + is_blacklist:true, + mode:"B", + regex:"d2VkcmZoaXdlZGZoYnVp", + service_id:"ctfe" + }, + { + id:3546, + is_blacklist:true, + mode:"B", + regex:"d2VkcmZoaXdlZGZoYnVp", + service_id:"ctfe" + }, + { + id:3546, + is_blacklist:true, + mode:"B", + regex:"d2VkcmZoaXdlZGZoYnVp", + service_id:"ctfe" + } + ]) + + const updateInfo = async () => { + if (!srv_id) return + let error = false; + await serviceinfo(srv_id).then(res => { + setServiceInfo(res) + }).catch( + err =>{ + showNotification({ + autoClose: notification_time, + title: `Updater for ${srv_id} service failed [General Info]!`, + message: "[ "+err+" ]", + color: 'red', + icon: , + }); + error = true; + }) + if (error) return + await serviceregexlist(srv_id).then(res => { + setRegexesList(res) + }).catch( + err =>{ + showNotification({ + autoClose: notification_time, + title: `Updater for ${srv_id} service failed [Regex list]!`, + message: "[ "+err+" ]", + color: 'red', + icon: , + }); + error = true; + }) + } + + useEffect(()=>{ + updateInfo() + const updater = setInterval(updateInfo, update_freq) + return () => { clearInterval(updater) } + }, []); + + return <> + + {regexesList.length === 0? + <> No regex found for this service! Add one clicking the add button above: + + {regexesList.map( (regexInfo) => )} + + } + +} + +export default ServiceDetails; diff --git a/frontend/src/reportWebVitals.ts b/frontend/src/reportWebVitals.ts deleted file mode 100755 index 49a2a16..0000000 --- a/frontend/src/reportWebVitals.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { ReportHandler } from 'web-vitals'; - -const reportWebVitals = (onPerfEntry?: ReportHandler) => { - if (onPerfEntry && onPerfEntry instanceof Function) { - import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { - getCLS(onPerfEntry); - getFID(onPerfEntry); - getFCP(onPerfEntry); - getLCP(onPerfEntry); - getTTFB(onPerfEntry); - }); - } -}; - -export default reportWebVitals; diff --git a/frontend/src/setupTests.ts b/frontend/src/setupTests.ts deleted file mode 100755 index 8f2609b..0000000 --- a/frontend/src/setupTests.ts +++ /dev/null @@ -1,5 +0,0 @@ -// jest-dom adds custom jest matchers for asserting on DOM nodes. -// allows you to do things like: -// expect(element).toHaveTextContent(/react/i) -// learn more: https://github.com/testing-library/jest-dom -import '@testing-library/jest-dom';