diff options
Diffstat (limited to 'frontend/src/views')
-rw-r--r-- | frontend/src/views/App.js | 16 | ||||
-rw-r--r-- | frontend/src/views/Connections.js | 19 | ||||
-rw-r--r-- | frontend/src/views/Filters.js | 98 | ||||
-rw-r--r-- | frontend/src/views/Filters.scss | 0 | ||||
-rw-r--r-- | frontend/src/views/Header.js | 37 |
5 files changed, 145 insertions, 25 deletions
diff --git a/frontend/src/views/App.js b/frontend/src/views/App.js index e3119aa..14ff7bf 100644 --- a/frontend/src/views/App.js +++ b/frontend/src/views/App.js @@ -5,26 +5,32 @@ import MainPane from "./MainPane"; import Footer from "./Footer"; import {BrowserRouter as Router, Route, Switch} from "react-router-dom"; import Services from "./Services"; +import Filters from "./Filters"; class App extends Component { constructor(props) { super(props); this.state = { - servicesShow: false + servicesWindowOpen: false, + filterWindowOpen: false }; } render() { - let modal = ""; - if (this.state.servicesShow) { - modal = <Services onHide={() => this.setState({servicesShow: false})}/>; + let modal; + if (this.state.servicesWindowOpen) { + modal = <Services onHide={() => this.setState({servicesWindowOpen: false})}/>; + } + if (this.state.filterWindowOpen) { + modal = <Filters onHide={() => this.setState({filterWindowOpen: false})}/>; } return ( <div className="app"> <Router> - <Header onOpenServices={() => this.setState({servicesShow: true})}/> + <Header onOpenServices={() => this.setState({servicesWindowOpen: true})} + onOpenFilters={() => this.setState({filterWindowOpen: true})}/> <Switch> <Route path="/connections/:id" children={<MainPane/>}/> <Route path="/" children={<MainPane/>}/> diff --git a/frontend/src/views/Connections.js b/frontend/src/views/Connections.js index 9b9fe35..62733d7 100644 --- a/frontend/src/views/Connections.js +++ b/frontend/src/views/Connections.js @@ -1,6 +1,6 @@ import React, {Component} from 'react'; import './Connections.scss'; -import axios from 'axios' +import axios from 'axios'; import Connection from "../components/Connection"; import Table from 'react-bootstrap/Table'; import {Redirect} from 'react-router'; @@ -15,7 +15,6 @@ class Connections extends Component { connections: [], firstConnection: null, lastConnection: null, - showHidden: false, prevParams: null, flagRule: null, rules: null, @@ -33,7 +32,7 @@ class Connections extends Component { } componentDidMount() { - this.loadConnections({limit: this.queryLimit, hidden: this.state.showHidden}) + this.loadConnections({limit: this.queryLimit}) .then(() => this.setState({loaded: true})); } @@ -45,7 +44,7 @@ class Connections extends Component { componentDidUpdate(prevProps, prevState, snapshot) { if (this.state.loaded && prevProps.location.search !== this.props.location.search) { this.setState({queryString: this.props.location.search}); - this.loadConnections({limit: this.queryLimit, hidden: this.state.showHidden}) + this.loadConnections({limit: this.queryLimit}) .then(() => console.log("Connections reloaded after query string update")); } } @@ -53,16 +52,12 @@ class Connections extends Component { handleScroll(e) { let relativeScroll = e.currentTarget.scrollTop / (e.currentTarget.scrollHeight - e.currentTarget.clientHeight); if (!this.state.loading && relativeScroll > this.scrollBottomThreashold) { - this.loadConnections({ - from: this.state.lastConnection.id, limit: this.queryLimit, - hidden: this.state.showHidden - }).then(() => console.log("Following connections loaded")); + this.loadConnections({from: this.state.lastConnection.id, limit: this.queryLimit,}) + .then(() => console.log("Following connections loaded")); } if (!this.state.loading && relativeScroll < this.scrollTopThreashold) { - this.loadConnections({ - to: this.state.firstConnection.id, limit: this.queryLimit, - hidden: this.state.showHidden - }).then(() => console.log("Previous connections loaded")); + this.loadConnections({to: this.state.firstConnection.id, limit: this.queryLimit,}) + .then(() => console.log("Previous connections loaded")); } } diff --git a/frontend/src/views/Filters.js b/frontend/src/views/Filters.js new file mode 100644 index 0000000..23d3a00 --- /dev/null +++ b/frontend/src/views/Filters.js @@ -0,0 +1,98 @@ +import React, {Component} from 'react'; +import './Services.scss'; +import {Button, Col, Container, Modal, Row, Table} from "react-bootstrap"; +import {filtersDefinitions, filtersNames} from "../components/filters/FiltersDefinitions"; + +class Filters extends Component { + + constructor(props) { + super(props); + this.state = {}; + filtersNames.forEach(elem => this.state[`${elem}_active`] = false); + } + + componentDidMount() { + let newState = {}; + filtersNames.forEach(elem => newState[`${elem}_active`] = localStorage.getItem(`filters.${elem}`) === "true"); + this.setState(newState); + } + + checkboxChangesHandler(filterName, event) { + this.setState({[`${filterName}_active`]: event.target.checked}); + localStorage.setItem(`filters.${filterName}`, event.target.checked); + if (typeof window !== "undefined") { + window.dispatchEvent(new Event("quick-filters")); + } + } + + generateRows(filtersNames) { + return filtersNames.map(name => + <tr> + <td><input type="checkbox" + checked={this.state[`${name}_active`]} + onChange={event => this.checkboxChangesHandler(name, event)} /></td> + <td>{filtersDefinitions[name]}</td> + </tr> + ); + } + + render() { + return ( + <Modal + {...this.props} + show="true" + size="lg" + aria-labelledby="filters-dialog" + centered + > + <Modal.Header> + <Modal.Title id="filters-dialog"> + ~/filters + </Modal.Title> + </Modal.Header> + <Modal.Body> + <Container> + <Row> + <Col md={6}> + <Table borderless size="sm" className="filters-table"> + <thead> + <tr> + <th>show</th> + <th>filter</th> + </tr> + </thead> + <tbody> + {this.generateRows(["service_port", "client_address", "min_duration", + "min_bytes", "started_after", "closed_after", "marked"])} + </tbody> + </Table> + </Col> + <Col md={6}> + <Table borderless size="sm" className="filters-table"> + <thead> + <tr> + <th>show</th> + <th>filter</th> + </tr> + </thead> + <tbody> + {this.generateRows(["matched_rules", "client_port", "max_duration", + "max_bytes", "started_before", "closed_before", "hidden"])} + </tbody> + </Table> + </Col> + + </Row> + + + </Container> + </Modal.Body> + <Modal.Footer className="dialog-footer"> + <Button variant="red" onClick={this.props.onHide}>close</Button> + </Modal.Footer> + </Modal> + ); + } +} + +export default Filters; diff --git a/frontend/src/views/Filters.scss b/frontend/src/views/Filters.scss new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/frontend/src/views/Filters.scss diff --git a/frontend/src/views/Header.js b/frontend/src/views/Header.js index 5118ec3..007be74 100644 --- a/frontend/src/views/Header.js +++ b/frontend/src/views/Header.js @@ -2,15 +2,18 @@ import React, {Component} from 'react'; import Typed from 'typed.js'; import './Header.scss'; import {Button} from "react-bootstrap"; -import ServicePortFilter from "../components/ServicePortFilter"; +import StringConnectionsFilter from "../components/filters/StringConnectionsFilter"; +import {cleanNumber, validateIpAddress, validateMin, validatePort} from "../utils"; +import RulesConnectionsFilter from "../components/filters/RulesConnectionsFilter"; +import {filtersDefinitions, filtersNames} from "../components/filters/FiltersDefinitions"; class Header extends Component { constructor(props) { super(props); - this.state = { - servicesShow: false - }; + this.state = {}; + filtersNames.forEach(elem => this.state[`${elem}_active`] = false); + this.fetchStateFromLocalStorage = this.fetchStateFromLocalStorage.bind(this); } componentDidMount() { @@ -20,13 +23,33 @@ class Header extends Component { cursorChar: "❚" }; this.typed = new Typed(this.el, options); + + this.fetchStateFromLocalStorage(); + + if (typeof window !== "undefined") { + window.addEventListener("quick-filters", this.fetchStateFromLocalStorage); + } } componentWillUnmount() { this.typed.destroy(); + + if (typeof window !== "undefined") { + window.removeEventListener("quick-filters", this.fetchStateFromLocalStorage); + } + } + + fetchStateFromLocalStorage() { + let newState = {}; + filtersNames.forEach(elem => newState[`${elem}_active`] = localStorage.getItem(`filters.${elem}`) === "true"); + this.setState(newState); } render() { + let quickFilters = filtersNames.filter(name => this.state[`${name}_active`]) + .map(name => filtersDefinitions[name]) + .slice(0, 5); + return ( <header className="header container-fluid"> <div className="row"> @@ -41,16 +64,14 @@ class Header extends Component { <div className="col-auto"> <div className="filters-bar-wrapper"> <div className="filters-bar"> - <ServicePortFilter /> - {/*<ServicePortFilter name="started_before" default="infinity" />*/} - {/*<ServicePortFilter name="started_after" default="-infinity" />*/} - + {quickFilters} </div> </div> </div> <div className="col"> <div className="header-buttons"> + <Button onClick={this.props.onOpenFilters}>filters</Button> <Button variant="yellow" size="sm">pcaps</Button> <Button variant="blue">rules</Button> <Button variant="red" onClick={this.props.onOpenServices}> |