diff options
Diffstat (limited to 'frontend/src/views')
-rw-r--r-- | frontend/src/views/App.js | 19 | ||||
-rw-r--r-- | frontend/src/views/Connections.js | 61 | ||||
-rw-r--r-- | frontend/src/views/Connections.scss | 32 | ||||
-rw-r--r-- | frontend/src/views/Header.js | 22 | ||||
-rw-r--r-- | frontend/src/views/MainPane.js | 10 | ||||
-rw-r--r-- | frontend/src/views/Services.js | 142 | ||||
-rw-r--r-- | frontend/src/views/Services.scss | 16 |
7 files changed, 242 insertions, 60 deletions
diff --git a/frontend/src/views/App.js b/frontend/src/views/App.js index 4d80da5..2b444a2 100644 --- a/frontend/src/views/App.js +++ b/frontend/src/views/App.js @@ -4,20 +4,35 @@ import './App.scss'; import MainPane from "./MainPane"; import Footer from "./Footer"; import {Route, BrowserRouter as Router, Switch} from "react-router-dom"; +import Services from "./Services"; class App extends Component { + constructor(props) { + super(props); + this.state = { + servicesShow: false + }; + } + render() { + let modal = "" + if (this.state.servicesShow) { + modal = <Services onHide={() => this.setState({servicesShow: false})} /> + } + return ( <div className="app"> <Router> - <Header/> + <Header onOpenServices={() => this.setState({servicesShow: true})}/> <Switch> + <Route path="/connections/:id" children={<MainPane/>} /> <Route path="/" children={<MainPane/>} /> - <Route path="/connection/:id" children={<MainPane/>} /> </Switch> + {modal} <Footer/> </Router> + </div> ); } diff --git a/frontend/src/views/Connections.js b/frontend/src/views/Connections.js index 5876a40..fa7798e 100644 --- a/frontend/src/views/Connections.js +++ b/frontend/src/views/Connections.js @@ -2,8 +2,8 @@ import React, {Component} from 'react'; import './Connections.scss'; import axios from 'axios' import Connection from "../components/Connection"; -import {Link} from "react-router-dom"; import Table from 'react-bootstrap/Table'; +import {Redirect} from 'react-router'; class Connections extends Component { constructor(props) { @@ -19,34 +19,16 @@ class Connections extends Component { } render() { - let connection = { - "id": "5dd95ff0fe7ae01ae7f419c2", - "ip_src": "10.62.82.1", - "ip_dst": "10.62.82.2", - "port_src": 59113, - "port_dst": 23179, - "started_at": "2019-11-23T16:36:00.1Z", - "closed_at": "2019-11-23T16:36:00.971Z", - "client_bytes": 331, - "server_bytes": 85, - "client_documents": 1, - "server_documents": 1, - "processed_at": "2020-04-21T17:10:29.532Z", - "matched_rules": [], - "hidden": false, - "marked": true, - "comment": "", - "service": { - "port": 23179, - "name": "kaboom", - "color": "#3C6D3C", - "notes": "wdddoddddddw" - } + let redirect = "" + if (this.state.selected) { + redirect = <Redirect push to={"/connections/" + this.state.selected} />; } return ( + <div className="connections"> - <Table striped hover> + <div className="connections-header-padding"/> + <Table borderless size="sm"> <thead> <tr> <th>service</th> @@ -61,31 +43,16 @@ class Connections extends Component { </tr> </thead> <tbody> - <tr> - <td>1</td> - <td>Mark</td> - <td>Otto</td> - <td>@mdo</td> - </tr> - <tr> - <td>2</td> - <td>Jacob</td> - <td>Thornton</td> - <td>@fat</td> - </tr> - <tr> - <td>3</td> - <td colSpan="2">Larry the Bird</td> - <td>@twitter</td> - </tr> + { + this.state.connections.map(c => + <Connection key={c.id} data={c} onSelected={() => this.setState({selected: c.id})} + selected={this.state.selected === c.id}/> + ) + } </tbody> </Table> - { - this.state.connections.map(c => - <Link to={"/connection/" + c.id}><Connection data={c} /></Link> - ) - } + {redirect} </div> ); } diff --git a/frontend/src/views/Connections.scss b/frontend/src/views/Connections.scss index da74e11..6d2de3f 100644 --- a/frontend/src/views/Connections.scss +++ b/frontend/src/views/Connections.scss @@ -2,12 +2,40 @@ .connections { background-color: $color-primary-3; - padding: 10px 10px 10px 10px; + padding: 0 10px; + position: relative; height: 100%; overflow: auto; .table { - color: $color-primary-4; + margin-top: 10px; } + + .connections-header-padding { + position: sticky; + height: 10px; + background-color: $color-primary-3; + top: 0; + left: 0; + right: 0; + margin-bottom: -10px; + } + + th { + background-color: $color-primary-2; + border-top: 3px solid $color-primary-3; + border-bottom: 3px solid $color-primary-3; + font-size: 13.5px; + + position: sticky; + top: 10px; + padding: 5px; + } + + &:hover::-webkit-scrollbar-thumb { + background: $color-secondary-2; + } + + }
\ No newline at end of file diff --git a/frontend/src/views/Header.js b/frontend/src/views/Header.js index b3f919b..ac272e6 100644 --- a/frontend/src/views/Header.js +++ b/frontend/src/views/Header.js @@ -1,9 +1,17 @@ import React, {Component} from 'react'; import Typed from 'typed.js'; import './Header.scss'; +import {Button} from "react-bootstrap"; class Header extends Component { + constructor(props) { + super(props); + this.state = { + servicesShow: false + }; + } + componentDidMount() { const options = { strings: ["caronte$ "], @@ -28,15 +36,11 @@ class Header extends Component { </div> <div className="col"> <div className="header-buttons"> - <button className="btn-primary"> - ➕ pcaps - </button> - <button className="btn-primary"> - ➕ rules - </button> - <button className="btn-primary"> - ➕ services - </button> + <Button variant="yellow" size="sm">pcaps</Button> + <Button variant="blue">rules</Button> + <Button variant="red" onClick={this.props.onOpenServices}> + services + </Button> </div> </div> </div> diff --git a/frontend/src/views/MainPane.js b/frontend/src/views/MainPane.js index 88b5376..0fc083e 100644 --- a/frontend/src/views/MainPane.js +++ b/frontend/src/views/MainPane.js @@ -26,6 +26,16 @@ class MainPane extends Component { } componentDidMount() { + if (this.props.match.params.id !== this.state.id) { + const id = this.props.match.params.id; + this.setState({id: id}); + + axios.get(`/api/streams/${id}`).then(res => this.setState({connectionContent: res.data})) + + + } + + } render() { diff --git a/frontend/src/views/Services.js b/frontend/src/views/Services.js new file mode 100644 index 0000000..1b3789d --- /dev/null +++ b/frontend/src/views/Services.js @@ -0,0 +1,142 @@ +import React, {Component} from 'react'; +import './Services.scss'; +import {Button, ButtonGroup, Col, Container, Form, FormControl, InputGroup, Modal, Row, Table} from "react-bootstrap"; +import axios from 'axios' +import {createCurlCommand} from '../utils'; + +class Services extends Component { + + constructor(props) { + super(props); + this.state = { + services: {}, + port: "", + portValid: false + } + + this.portChanged = this.portChanged.bind(this); + } + + componentDidMount() { + axios.get("/api/services").then(res => this.setState({services: res.data})) + } + + portChanged(event) { + let value = event.target.value.replace(/[^\d]/gi, '') + let intValue = parseInt(value) + this.setState({port: value, portValid: intValue > 0 && intValue <= 65565}) + + + } + + + render() { + let curl = createCurlCommand("/services", { + "port": this.state.port, + "name": "aaaaa", + "color": "#fff", + "notes": "aaa" + }) + + let rows = Object.values(this.state.services).map(s => + <tr> + <td><Button size="sm" style={{ + "backgroundColor": s.color + }}>edit</Button></td> + <td>{s.port}</td> + <td>{s.name}</td> + </tr> + ) + + + + + return ( + <Modal + {...this.props} + show="true" + size="lg" + aria-labelledby="contained-modal-title-vcenter" + centered + > + <Modal.Header> + <Modal.Title id="contained-modal-title-vcenter"> + ~/services + </Modal.Title> + </Modal.Header> + <Modal.Body> + <Container> + <Row> + <Col md={7}> + <Table borderless size="sm" className="services-list"> + <thead> + <tr> + <th><Button size="sm">new</Button></th> + <th>name</th> + <th>port</th> + </tr> + </thead> + <tbody> + {rows} + </tbody> + </Table> + </Col> + <Col md={5}> + <Form> + <Form.Group controlId="servicePort"> + <Form.Label>port:</Form.Label> + <Form.Control type="text" onChange={this.portChanged} value={this.state.port} /> + <Form.Text className="text-muted"> + {!this.state.portValid ? "assert(1 <= port <= 65565)" : ""} + </Form.Text> + </Form.Group> + + <Form.Group controlId="serviceName"> + <Form.Label>name:</Form.Label> + <Form.Control type="text" required min={3} max={16} /> + <Form.Text className="text-muted"> + {"assert(len(name) >= 3)"} + </Form.Text> + </Form.Group> + + <Form.Group controlId="serviceColor"> + <Form.Label>color:</Form.Label> + <ButtonGroup aria-label="Basic example"> + <Button variant="secondary">Left</Button> + <Button variant="secondary">Middle</Button> + <Button variant="secondary">Right</Button> + </ButtonGroup> + </Form.Group> + + <Form.Group controlId="serviceNotes"> + <Form.Label>notes:</Form.Label> + <Form.Control type="textarea" /> + </Form.Group> + </Form> + + + </Col> + + </Row> + + <Row> + <Col md={12}> + <InputGroup> + <FormControl as="textarea" rows={9} className="curl-output" readOnly={true}>{curl} + </FormControl> + </InputGroup> + + </Col> + </Row> + </Container> + </Modal.Body> + <Modal.Footer className="dialog-footer"> + <Button variant="green" onClick={this.props.onHide}>save</Button> + <Button variant="red" onClick={this.props.onHide}>close</Button> + </Modal.Footer> + </Modal> + ); + } +} + +export default Services; diff --git a/frontend/src/views/Services.scss b/frontend/src/views/Services.scss new file mode 100644 index 0000000..fd65beb --- /dev/null +++ b/frontend/src/views/Services.scss @@ -0,0 +1,16 @@ +.curl-output { + width: 100%; + font-size: 13px; +} + +.services-list { + .btn { + width: 150px; + } +} + +.dialog-footer { + .btn { + width: 80px; + } +}
\ No newline at end of file |