diff options
Diffstat (limited to 'frontend/src/views')
-rw-r--r-- | frontend/src/views/App.js | 49 | ||||
-rw-r--r-- | frontend/src/views/App.scss | 15 | ||||
-rw-r--r-- | frontend/src/views/Connections.js | 201 | ||||
-rw-r--r-- | frontend/src/views/Connections.scss | 37 | ||||
-rw-r--r-- | frontend/src/views/Filters.js | 99 | ||||
-rw-r--r-- | frontend/src/views/Footer.js | 19 | ||||
-rw-r--r-- | frontend/src/views/Footer.scss | 13 | ||||
-rw-r--r-- | frontend/src/views/Header.js | 92 | ||||
-rw-r--r-- | frontend/src/views/Header.scss | 34 |
9 files changed, 0 insertions, 559 deletions
diff --git a/frontend/src/views/App.js b/frontend/src/views/App.js deleted file mode 100644 index fb4454c..0000000 --- a/frontend/src/views/App.js +++ /dev/null @@ -1,49 +0,0 @@ -import React, {Component} from 'react'; -import './App.scss'; -import Header from "./Header"; -import MainPane from "../components/panels/MainPane"; -import Footer from "./Footer"; -import {BrowserRouter as Router} from "react-router-dom"; -import Filters from "./Filters"; -import backend from "../backend"; -import ConfigurationPane from "../components/panels/ConfigurationPane"; - -class App extends Component { - - constructor(props) { - super(props); - - this.state = {}; - } - - componentDidMount() { - backend.get("/api/services").then(_ => this.setState({configured: true})); - } - - render() { - let modal; - if (this.state.filterWindowOpen && this.state.configured) { - modal = <Filters onHide={() => this.setState({filterWindowOpen: false})}/>; - } - - return ( - <div className="main"> - <Router> - <div className="main-header"> - <Header onOpenFilters={() => this.setState({filterWindowOpen: true})} /> - </div> - <div className="main-content"> - {this.state.configured ? <MainPane /> : - <ConfigurationPane onConfigured={() => this.setState({configured: true})} />} - {modal} - </div> - <div className="main-footer"> - {this.state.configured && <Footer/>} - </div> - </Router> - </div> - ); - } -} - -export default App; diff --git a/frontend/src/views/App.scss b/frontend/src/views/App.scss deleted file mode 100644 index 5c5bd99..0000000 --- a/frontend/src/views/App.scss +++ /dev/null @@ -1,15 +0,0 @@ - -.main { - display: flex; - flex-direction: column; - height: 100vh; - - .main-content { - overflow: hidden; - flex: 1 1; - } - - .main-header, .main-footer { - flex: 0 0; - } -} diff --git a/frontend/src/views/Connections.js b/frontend/src/views/Connections.js deleted file mode 100644 index 73979c4..0000000 --- a/frontend/src/views/Connections.js +++ /dev/null @@ -1,201 +0,0 @@ -import React, {Component} from 'react'; -import './Connections.scss'; -import Connection from "../components/Connection"; -import Table from 'react-bootstrap/Table'; -import {Redirect} from 'react-router'; -import {withRouter} from "react-router-dom"; -import backend from "../backend"; -import ConnectionMatchedRules from "../components/ConnectionMatchedRules"; - -class Connections extends Component { - - constructor(props) { - super(props); - this.state = { - loading: false, - connections: [], - firstConnection: null, - lastConnection: null, - prevParams: null, - flagRule: null, - rules: null, - queryString: null - }; - - this.scrollTopThreashold = 0.00001; - this.scrollBottomThreashold = 0.99999; - this.maxConnections = 500; - this.queryLimit = 50; - } - - componentDidMount() { - this.loadConnections({limit: this.queryLimit}) - .then(() => this.setState({loaded: true})); - if (this.props.initialConnection != null) { - this.setState({selected: this.props.initialConnection.id}); - // TODO: scroll to initial connection - } - } - - connectionSelected = (c) => { - this.setState({selected: c.id}); - this.props.onSelected(c); - }; - - 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}) - .then(() => console.log("Connections reloaded after query string update")); - } - } - - 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,}) - .then(() => console.log("Following connections loaded")); - } - if (!this.state.loading && relativeScroll < this.scrollTopThreashold) { - this.loadConnections({to: this.state.firstConnection.id, limit: this.queryLimit,}) - .then(() => console.log("Previous connections loaded")); - } - }; - - addServicePortFilter = (port) => { - const urlParams = new URLSearchParams(this.props.location.search); - urlParams.set("service_port", port); - this.setState({queryString: "?" + urlParams}); - }; - - addMatchedRulesFilter = (matchedRule) => { - const urlParams = new URLSearchParams(this.props.location.search); - const oldMatchedRules = urlParams.getAll("matched_rules") || []; - - if (!oldMatchedRules.includes(matchedRule)) { - urlParams.append("matched_rules", matchedRule); - this.setState({queryString: "?" + urlParams}); - } - }; - - async loadConnections(params) { - let url = "/api/connections"; - const urlParams = new URLSearchParams(this.props.location.search); - for (const [name, value] of Object.entries(params)) { - urlParams.set(name, value); - } - - this.setState({loading: true, prevParams: params}); - let res = (await backend.get(`${url}?${urlParams}`)).json; - - let connections = this.state.connections; - let firstConnection = this.state.firstConnection; - let lastConnection = this.state.lastConnection; - - if (params !== undefined && params.from !== undefined) { - if (res.length > 0) { - connections = this.state.connections.concat(res); - lastConnection = connections[connections.length - 1]; - if (connections.length > this.maxConnections) { - connections = connections.slice(connections.length - this.maxConnections, - connections.length - 1); - firstConnection = connections[0]; - } - } - } else if (params !== undefined && params.to !== undefined) { - if (res.length > 0) { - connections = res.concat(this.state.connections); - firstConnection = connections[0]; - if (connections.length > this.maxConnections) { - connections = connections.slice(0, this.maxConnections); - lastConnection = connections[this.maxConnections - 1]; - } - } - } else { - if (res.length > 0) { - connections = res; - firstConnection = connections[0]; - lastConnection = connections[connections.length - 1]; - } else { - connections = []; - firstConnection = null; - lastConnection = null; - } - } - - let rules = this.state.rules; - if (rules === null) { - rules = (await backend.get("/api/rules")).json; - } - - this.setState({ - loading: false, - connections: connections, - rules: rules, - firstConnection: firstConnection, - lastConnection: lastConnection - }); - } - - render() { - let redirect; - let queryString = this.state.queryString !== null ? this.state.queryString : ""; - if (this.state.selected) { - let format = this.props.match.params.format; - format = format !== undefined ? "/" + format : ""; - redirect = <Redirect push to={`/connections/${this.state.selected}${format}${queryString}`} />; - } - - let loading = null; - if (this.state.loading) { - loading = <tr> - <td colSpan={9}>Loading...</td> - </tr>; - } - - return ( - <div className="connections" onScroll={this.handleScroll}> - <div className="connections-header-padding"/> - <Table borderless size="sm"> - <thead> - <tr> - <th>service</th> - <th>srcip</th> - <th>srcport</th> - <th>dstip</th> - <th>dstport</th> - <th>started_at</th> - <th>duration</th> - <th>up</th> - <th>down</th> - <th>actions</th> - </tr> - </thead> - <tbody> - { - this.state.connections.flatMap(c => { - return [<Connection key={c.id} data={c} onSelected={() => this.connectionSelected(c)} - selected={this.state.selected === c.id} - onMarked={marked => c.marked = marked} - onEnabled={enabled => c.hidden = !enabled} - addServicePortFilter={this.addServicePortFilter} />, - c.matched_rules.length > 0 && - <ConnectionMatchedRules key={c.id + "_m"} matchedRules={c.matched_rules} - rules={this.state.rules} - addMatchedRulesFilter={this.addMatchedRulesFilter} /> - ]; - }) - } - {loading} - </tbody> - </Table> - - {redirect} - </div> - ); - } - -} - - -export default withRouter(Connections); diff --git a/frontend/src/views/Connections.scss b/frontend/src/views/Connections.scss deleted file mode 100644 index c7bd1df..0000000 --- a/frontend/src/views/Connections.scss +++ /dev/null @@ -1,37 +0,0 @@ -@import "../colors.scss"; - -.connections { - position: relative; - overflow: auto; - height: 100%; - padding: 0 10px; - background-color: $color-primary-3; - - .table { - margin-top: 10px; - } - - .connections-header-padding { - position: sticky; - top: 0; - right: 0; - left: 0; - height: 10px; - margin-bottom: -10px; - background-color: $color-primary-3; - } - - th { - font-size: 13.5px; - position: sticky; - top: 10px; - padding: 5px; - border-top: 3px solid $color-primary-3; - border-bottom: 3px solid $color-primary-3; - background-color: $color-primary-2; - } - - &:hover::-webkit-scrollbar-thumb { - background: $color-secondary-2; - } -} diff --git a/frontend/src/views/Filters.js b/frontend/src/views/Filters.js deleted file mode 100644 index ba7d467..0000000 --- a/frontend/src/views/Filters.js +++ /dev/null @@ -1,99 +0,0 @@ -import React, {Component} from 'react'; -import {Col, Container, Modal, Row, Table} from "react-bootstrap"; -import {filtersDefinitions, filtersNames} from "../components/filters/FiltersDefinitions"; -import ButtonField from "../components/fields/ButtonField"; - -class Filters extends Component { - - constructor(props) { - super(props); - let newState = {}; - filtersNames.forEach(elem => newState[`${elem}_active`] = false); - this.state = newState; - } - - 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 key={name}> - <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"> - <ButtonField variant="red" bordered onClick={this.props.onHide} name="close" /> - </Modal.Footer> - </Modal> - ); - } -} - -export default Filters; diff --git a/frontend/src/views/Footer.js b/frontend/src/views/Footer.js deleted file mode 100644 index 0a3c5a3..0000000 --- a/frontend/src/views/Footer.js +++ /dev/null @@ -1,19 +0,0 @@ -import React, {Component} from 'react'; -import './Footer.scss'; - -class Footer extends Component { - - render() { - return ( - <footer className="footer container-fluid"> - <div className="row"> - <div className="col-12"> - <div className="footer-timeline">timeline - <a href="https://github.com/eciavatta/caronte/issues/12">to be implemented</a></div> - </div> - </div> - </footer> - ); - } -} - -export default Footer; diff --git a/frontend/src/views/Footer.scss b/frontend/src/views/Footer.scss deleted file mode 100644 index 6ec4a62..0000000 --- a/frontend/src/views/Footer.scss +++ /dev/null @@ -1,13 +0,0 @@ -@import "../colors.scss"; - -.footer { - padding: 15px 30px; - - > .row { - background-color: $color-primary-0; - } - - .footer-timeline { - height: 100px; - } -} diff --git a/frontend/src/views/Header.js b/frontend/src/views/Header.js deleted file mode 100644 index 944f1d5..0000000 --- a/frontend/src/views/Header.js +++ /dev/null @@ -1,92 +0,0 @@ -import React, {Component} from 'react'; -import Typed from 'typed.js'; -import './Header.scss'; -import {filtersDefinitions, filtersNames} from "../components/filters/FiltersDefinitions"; -import {Link} from "react-router-dom"; -import ButtonField from "../components/fields/ButtonField"; - -class Header extends Component { - - constructor(props) { - super(props); - let newState = {}; - filtersNames.forEach(elem => newState[`${elem}_active`] = false); - this.state = newState; - this.fetchStateFromLocalStorage = this.fetchStateFromLocalStorage.bind(this); - } - - componentDidMount() { - const options = { - strings: ["caronte$ "], - typeSpeed: 50, - 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 => <React.Fragment key={name} >{filtersDefinitions[name]}</React.Fragment>) - .slice(0, 5); - - return ( - <header className="header container-fluid"> - <div className="row"> - <div className="col-auto"> - <h1 className="header-title type-wrap"> - <span style={{whiteSpace: 'pre'}} ref={(el) => { - this.el = el; - }}/> - </h1> - </div> - - <div className="col-auto"> - <div className="filters-bar"> - {quickFilters} - </div> - </div> - - <div className="col"> - <div className="header-buttons"> - <ButtonField variant="pink" onClick={this.props.onOpenFilters} name="filters" bordered /> - <Link to="/pcaps"> - <ButtonField variant="purple" name="pcaps" bordered /> - </Link> - <Link to="/rules"> - <ButtonField variant="deep-purple" name="rules" bordered /> - </Link> - <Link to="/services"> - <ButtonField variant="indigo" name="services" bordered /> - </Link> - <Link to="/config"> - <ButtonField variant="blue" name="config" bordered /> - </Link> - </div> - </div> - </div> - </header> - ); - } -} - -export default Header; diff --git a/frontend/src/views/Header.scss b/frontend/src/views/Header.scss deleted file mode 100644 index 0711159..0000000 --- a/frontend/src/views/Header.scss +++ /dev/null @@ -1,34 +0,0 @@ -@import "../colors.scss"; - -.header { - height: 80px; - padding: 15px 30px; - - > .row { - background-color: $color-primary-0; - } - - .header-title { - width: 200px; - margin: 5px 0 5px -5px; - } - - .header-buttons { - display: flex; - justify-content: flex-end; - margin: 7px 0; - - .button-field { - margin-left: 7px; - } - } - - .filters-bar { - padding: 3px 0; - - .filter { - display: inline-block; - margin-right: 10px; - } - } -} |