diff options
author | Emiliano Ciavatta | 2020-04-29 13:13:20 +0000 |
---|---|---|
committer | Emiliano Ciavatta | 2020-04-29 13:13:20 +0000 |
commit | 3f3ae121ef082a430f4bdc84ab7970a5633d552a (patch) | |
tree | dc08aea5263e33d9b456bf03a99a33bc261a723d /frontend/src | |
parent | d1eeb1a6b3eed3c666cc6f94ba2a932abbce8515 (diff) |
Frontend checkpoint
Diffstat (limited to 'frontend/src')
-rw-r--r-- | frontend/src/App.css | 38 | ||||
-rw-r--r-- | frontend/src/App.js | 26 | ||||
-rw-r--r-- | frontend/src/App.test.js | 9 | ||||
-rw-r--r-- | frontend/src/colors.scss | 11 | ||||
-rw-r--r-- | frontend/src/components/Connection.js | 73 | ||||
-rw-r--r-- | frontend/src/components/Connection.scss | 54 | ||||
-rw-r--r-- | frontend/src/components/ConnectionContent.js | 61 | ||||
-rw-r--r-- | frontend/src/components/ConnectionContent.scss | 28 | ||||
-rw-r--r-- | frontend/src/index.css | 13 | ||||
-rw-r--r-- | frontend/src/index.js | 5 | ||||
-rw-r--r-- | frontend/src/index.scss | 88 | ||||
-rw-r--r-- | frontend/src/views/App.js | 26 | ||||
-rw-r--r-- | frontend/src/views/App.scss | 2 | ||||
-rw-r--r-- | frontend/src/views/Connections.js | 96 | ||||
-rw-r--r-- | frontend/src/views/Connections.scss | 13 | ||||
-rw-r--r-- | frontend/src/views/Footer.js | 19 | ||||
-rw-r--r-- | frontend/src/views/Footer.scss | 14 | ||||
-rw-r--r-- | frontend/src/views/Header.js | 48 | ||||
-rw-r--r-- | frontend/src/views/Header.scss | 18 | ||||
-rw-r--r-- | frontend/src/views/MainPane.js | 49 | ||||
-rw-r--r-- | frontend/src/views/MainPane.scss | 9 |
21 files changed, 612 insertions, 88 deletions
diff --git a/frontend/src/App.css b/frontend/src/App.css deleted file mode 100644 index 74b5e05..0000000 --- a/frontend/src/App.css +++ /dev/null @@ -1,38 +0,0 @@ -.App { - text-align: center; -} - -.App-logo { - height: 40vmin; - pointer-events: none; -} - -@media (prefers-reduced-motion: no-preference) { - .App-logo { - animation: App-logo-spin infinite 20s linear; - } -} - -.App-header { - background-color: #282c34; - min-height: 100vh; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - font-size: calc(10px + 2vmin); - color: white; -} - -.App-link { - color: #61dafb; -} - -@keyframes App-logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} diff --git a/frontend/src/App.js b/frontend/src/App.js deleted file mode 100644 index ce9cbd2..0000000 --- a/frontend/src/App.js +++ /dev/null @@ -1,26 +0,0 @@ -import React from 'react'; -import logo from './logo.svg'; -import './App.css'; - -function App() { - return ( - <div className="App"> - <header className="App-header"> - <img src={logo} className="App-logo" alt="logo" /> - <p> - Edit <code>src/App.js</code> and save to reload. - </p> - <a - className="App-link" - href="https://reactjs.org" - target="_blank" - rel="noopener noreferrer" - > - Learn React - </a> - </header> - </div> - ); -} - -export default App; diff --git a/frontend/src/App.test.js b/frontend/src/App.test.js deleted file mode 100644 index 4db7ebc..0000000 --- a/frontend/src/App.test.js +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react'; -import { render } from '@testing-library/react'; -import App from './App'; - -test('renders learn react link', () => { - const { getByText } = render(<App />); - const linkElement = getByText(/learn react/i); - expect(linkElement).toBeInTheDocument(); -}); diff --git a/frontend/src/colors.scss b/frontend/src/colors.scss new file mode 100644 index 0000000..290a0cd --- /dev/null +++ b/frontend/src/colors.scss @@ -0,0 +1,11 @@ +$color-primary-0: #17223B; // Main Primary color */ +$color-primary-1: #040B1B; +$color-primary-2: #0F192E; +$color-primary-3: #1D2841; +$color-primary-4: #EAEAEA; + +$color-secondary-0: #FF6767; +$color-secondary-1: #A20A0A; +$color-secondary-2: #DF3030; +$color-secondary-3: #FF9D9D; +$color-secondary-4: #FFDFDF; diff --git a/frontend/src/components/Connection.js b/frontend/src/components/Connection.js new file mode 100644 index 0000000..4bdc8cd --- /dev/null +++ b/frontend/src/components/Connection.js @@ -0,0 +1,73 @@ +import React, {Component} from 'react'; +import './Connection.scss'; +import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"; +import { + faCloudDownloadAlt, + faCloudUploadAlt, + faComment, + faEyeSlash, + faHourglassHalf, + faLaptop, + faLink, + faServer, + faThumbtack, +} from '@fortawesome/free-solid-svg-icons' + +class Connection extends Component { + render() { + let conn = this.props.data + let serviceName = "assign" + let serviceColor = "#fff" + if (conn.service != null) { + serviceName = conn.service.name + serviceColor = conn.service.color + } + let startedAt = new Date(conn.started_at) + let closedAt = new Date(conn.closed_at) + let duration = ((closedAt - startedAt) / 1000).toFixed(3) + let timeInfo = `Started at ${startedAt}\nClosed at ${closedAt}\nProcessed at ${new Date(conn.processed_at)}` + + + return ( + <tr className={conn.marked ? "connection connection-marked" : "connection"}> + <div className="connection-header"> + <span className="connection-service"> + <button className="btn" style={{ + "backgroundColor": serviceColor + }}>{serviceName}</button> + </span> + <span className="connection-src"> + <FontAwesomeIcon icon={faLaptop}/> + <span className="connection-ip-port">{conn.ip_src}:{conn.port_src}</span> + </span> + <span className="connection-separator">{"->"}</span> + <span className="connection-dst"> + <FontAwesomeIcon icon={faServer}/> + <span className="connection-ip-port">{conn.ip_dst}:{conn.port_dst}</span> + </span> + + <span className="connection-duration" data-toggle="tooltip" data-placement="top" title={timeInfo}> + <FontAwesomeIcon icon={faHourglassHalf}/> + <span className="connection-seconds">{duration}s</span> + </span> + <span className="connection-bytes"> + <FontAwesomeIcon icon={faCloudDownloadAlt}/> + <span className="connection-bytes-count">{conn.client_bytes}</span> + <FontAwesomeIcon icon={faCloudUploadAlt}/> + <span className="connection-bytes-count">{conn.server_bytes}</span> + </span> + <span className="connection-hide"><FontAwesomeIcon icon={faEyeSlash}/></span> + <span className="connection-mark"><FontAwesomeIcon icon={faThumbtack}/></span> + <span className="connection-comment"><FontAwesomeIcon icon={faComment}/></span> + <span className="connection-link"><FontAwesomeIcon icon={faLink}/></span> + </div> + + + </tr> + ); + } + +} + + +export default Connection; diff --git a/frontend/src/components/Connection.scss b/frontend/src/components/Connection.scss new file mode 100644 index 0000000..8910cb4 --- /dev/null +++ b/frontend/src/components/Connection.scss @@ -0,0 +1,54 @@ +@import '../colors.scss'; + +.connection { + background-color: $color-primary-0; + margin-bottom: 5px; + + + &.connection-marked { + border-right: 5px solid $color-secondary-2; + } + + .connection-service { + padding: 0 12px 0 0; + + .btn { + font-size: 12px; + width: 120px; + } + } + + .connection-separator { + margin: 0 10px; + } + + .connection-duration { + margin-left: 15px; + + //.connection-seconds { + // width: 75px; + // display: inline-block; + // text-align: right; + //} + } + + .connection-bytes { + margin-left: 10px; + margin-right: 10px; + + .connection-bytes-count { + margin-right: 5px; + } + } + + .connection-hide, .connection-mark, .connection-comment, .connection-link { + margin-left: 5px; + } + + + svg { + margin-right: 6px; + } + +} + diff --git a/frontend/src/components/ConnectionContent.js b/frontend/src/components/ConnectionContent.js new file mode 100644 index 0000000..061282c --- /dev/null +++ b/frontend/src/components/ConnectionContent.js @@ -0,0 +1,61 @@ +import React, {Component} from 'react'; +import './ConnectionContent.scss'; +import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"; +import { + +} from '@fortawesome/free-solid-svg-icons' +import {useParams} from "react-router-dom"; +import { Dropdown } from 'react-bootstrap'; + +class ConnectionContent extends Component { + render() { + let content = this.props.connectionPayload + + console.log(content) + + if (content === undefined) { + return <div>nope</div> + } + + let payload = content.map(c => + <span key={c.id} className={c.from_client ? "from-client" : "from-server"} title="cccccc"> + {c.content} + + </span> + ) + + + + + return ( + <div className="connection-content"> + <div className="connection-content-options"> + <Dropdown> + <Dropdown.Toggle variant="success" id="dropdown-basic"> + format + </Dropdown.Toggle> + + <Dropdown.Menu> + <Dropdown.Item href="#/action-1">plain</Dropdown.Item> + <Dropdown.Item href="#/action-2">hex</Dropdown.Item> + <Dropdown.Item href="#/action-3">hexdump</Dropdown.Item> + <Dropdown.Item href="#/action-3">base32</Dropdown.Item> + <Dropdown.Item href="#/action-3">base64</Dropdown.Item> + <Dropdown.Item href="#/action-3">ascii</Dropdown.Item> + </Dropdown.Menu> + </Dropdown> + + + </div> + + <pre>{payload}</pre> + + + </div> + ); + } + +} + + +export default ConnectionContent; diff --git a/frontend/src/components/ConnectionContent.scss b/frontend/src/components/ConnectionContent.scss new file mode 100644 index 0000000..074d975 --- /dev/null +++ b/frontend/src/components/ConnectionContent.scss @@ -0,0 +1,28 @@ +@import '../colors.scss'; + +.connection-content { + background-color: $color-primary-3; + height: 100%; + overflow: auto; + + + pre { + background-color: $color-primary-0; + padding: 10px 20px; + word-break: break-all; + } + + .from-client { + color: #d4e0fc; + } + + .from-server { + color: $color-secondary-4; + + &:hover { + background-color: $color-primary-3; + border-top: 1px solid $color-primary-1; + } + + } +}
\ No newline at end of file diff --git a/frontend/src/index.css b/frontend/src/index.css deleted file mode 100644 index ec2585e..0000000 --- a/frontend/src/index.css +++ /dev/null @@ -1,13 +0,0 @@ -body { - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; -} diff --git a/frontend/src/index.js b/frontend/src/index.js index f5185c1..2e90371 100644 --- a/frontend/src/index.js +++ b/frontend/src/index.js @@ -1,7 +1,8 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import './index.css'; -import App from './App'; +import 'bootstrap/dist/css/bootstrap.css'; +import './index.scss'; +import App from './views/App'; import * as serviceWorker from './serviceWorker'; ReactDOM.render( diff --git a/frontend/src/index.scss b/frontend/src/index.scss new file mode 100644 index 0000000..5c18095 --- /dev/null +++ b/frontend/src/index.scss @@ -0,0 +1,88 @@ +@import url('https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500&display=swap'); +@import-normalize; + +@import 'colors.scss'; + + +body { + margin: 0; + font-family: 'Fira Code', monospace; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + background-color: $color-primary-2; + color: $color-primary-4; + + height: 100%; + max-height: 100%; +} + +pre { + font-family: 'Fira Code', monospace; + font-size: 14px; +} + +button { + :focus { + outline: none; + box-shadow: none; + } +} + +.btn { + border-radius: 0; + color: $color-primary-4; +} + +.btn-primary { + margin-left: 20px; + padding: 5px 12px; + background-color: $color-secondary-2; + font-weight: 500; + border: 0; + border-bottom: 5px solid $color-secondary-1; + + color: $color-secondary-4; + outline:none; + + + :focus, :active { + outline: none; + box-shadow: none; + } + +} + +.btn-primary:hover { + background-color: $color-secondary-1; + border-color: $color-secondary-1; + outline: none; +} + +a { + color: $color-primary-4; + + &:hover { + color: $color-primary-4; + text-decoration: none; + } +} + +/* width */ +::-webkit-scrollbar { + width: 12px; +} + +/* Track */ +::-webkit-scrollbar-track { + background: $color-primary-0; +} + +/* Handle */ +::-webkit-scrollbar-thumb { + background: $color-primary-1; +} + +/* Handle on hover */ +::-webkit-scrollbar-thumb:hover { + background: $color-secondary-2; +}
\ No newline at end of file diff --git a/frontend/src/views/App.js b/frontend/src/views/App.js new file mode 100644 index 0000000..4d80da5 --- /dev/null +++ b/frontend/src/views/App.js @@ -0,0 +1,26 @@ +import React, {Component} from 'react'; +import Header from "./Header"; +import './App.scss'; +import MainPane from "./MainPane"; +import Footer from "./Footer"; +import {Route, BrowserRouter as Router, Switch} from "react-router-dom"; + +class App extends Component { + + render() { + return ( + <div className="app"> + <Router> + <Header/> + <Switch> + <Route path="/" children={<MainPane/>} /> + <Route path="/connection/:id" children={<MainPane/>} /> + </Switch> + <Footer/> + </Router> + </div> + ); + } +} + +export default App; diff --git a/frontend/src/views/App.scss b/frontend/src/views/App.scss new file mode 100644 index 0000000..2ee17ac --- /dev/null +++ b/frontend/src/views/App.scss @@ -0,0 +1,2 @@ +.app { +}
\ No newline at end of file diff --git a/frontend/src/views/Connections.js b/frontend/src/views/Connections.js new file mode 100644 index 0000000..5876a40 --- /dev/null +++ b/frontend/src/views/Connections.js @@ -0,0 +1,96 @@ +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'; + +class Connections extends Component { + constructor(props) { + super(props); + this.state = { + connections: [], + }; + } + + + componentDidMount() { + axios.get("/api/connections").then(res => this.setState({connections: res.data})) + } + + 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" + } + } + + return ( + <div className="connections"> + <Table striped hover> + <thead> + <tr> + <th>service</th> + <th>srcip</th> + <th>dstip</th> + <th>srcport</th> + <th>dstport</th> + <th>duration</th> + <th>up</th> + <th>down</th> + <th>actions</th> + </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> + </tbody> + </Table> + + { + this.state.connections.map(c => + <Link to={"/connection/" + c.id}><Connection data={c} /></Link> + ) + } + </div> + ); + } + +} + + +export default Connections; diff --git a/frontend/src/views/Connections.scss b/frontend/src/views/Connections.scss new file mode 100644 index 0000000..da74e11 --- /dev/null +++ b/frontend/src/views/Connections.scss @@ -0,0 +1,13 @@ +@import '../colors.scss'; + +.connections { + background-color: $color-primary-3; + padding: 10px 10px 10px 10px; + + height: 100%; + overflow: auto; + + .table { + color: $color-primary-4; + } +}
\ No newline at end of file diff --git a/frontend/src/views/Footer.js b/frontend/src/views/Footer.js new file mode 100644 index 0000000..b6ffd9d --- /dev/null +++ b/frontend/src/views/Footer.js @@ -0,0 +1,19 @@ +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</div> + </div> + </div> + </footer> + ) + } +} + +export default Footer; diff --git a/frontend/src/views/Footer.scss b/frontend/src/views/Footer.scss new file mode 100644 index 0000000..9a8cacb --- /dev/null +++ b/frontend/src/views/Footer.scss @@ -0,0 +1,14 @@ +@import '../colors.scss'; + +.footer { + padding: 15px 30px; + + >.row { + background-color: $color-primary-0; + } + + .footer-timeline { + height: 100px; + } + +}
\ No newline at end of file diff --git a/frontend/src/views/Header.js b/frontend/src/views/Header.js new file mode 100644 index 0000000..b3f919b --- /dev/null +++ b/frontend/src/views/Header.js @@ -0,0 +1,48 @@ +import React, {Component} from 'react'; +import Typed from 'typed.js'; +import './Header.scss'; + +class Header extends Component { + + componentDidMount() { + const options = { + strings: ["caronte$ "], + typeSpeed: 50, + cursorChar: "❚" + }; + this.typed = new Typed(this.el, options); + } + + componentWillUnmount() { + this.typed.destroy(); + } + + render() { + return ( + <header className="header container-fluid"> + <div className="row"> + <div className="col"> + <h1 className="header-title type-wrap"> + <span style={{ whiteSpace: 'pre' }} ref={(el) => { this.el = el; }} /> + </h1> + </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> + </div> + </div> + </div> + </header> + ) + } +} + +export default Header; diff --git a/frontend/src/views/Header.scss b/frontend/src/views/Header.scss new file mode 100644 index 0000000..16c2dbd --- /dev/null +++ b/frontend/src/views/Header.scss @@ -0,0 +1,18 @@ +@import '../colors.scss'; + +.header { + padding: 15px 30px; + + >.row { + background-color: $color-primary-0; + } + + .header-title { + margin: 5px 0 5px -5px; + } + + .header-buttons { + margin: 5px 0; + text-align: right; + } +}
\ No newline at end of file diff --git a/frontend/src/views/MainPane.js b/frontend/src/views/MainPane.js new file mode 100644 index 0000000..88b5376 --- /dev/null +++ b/frontend/src/views/MainPane.js @@ -0,0 +1,49 @@ +import React, {Component} from 'react'; +import './MainPane.scss'; +import Connections from "./Connections"; +import ConnectionContent from "../components/ConnectionContent"; +import {withRouter} from "react-router-dom"; +import axios from 'axios' + +class MainPane extends Component { + + constructor(props) { + super(props); + this.state = { + id: null, + }; + } + + componentDidUpdate() { + 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})) + + + } + } + + componentDidMount() { + } + + render() { + return ( + <div className="main-pane"> + <div className="container-fluid"> + <div className="row"> + <div className="col-md-6 pane"> + <Connections/> + </div> + <div className="col-md-6 pl-0 pane"> + <ConnectionContent connectionPayload={this.state.connectionContent}/> + </div> + </div> + </div> + </div> + ); + } +} + +export default withRouter(MainPane); diff --git a/frontend/src/views/MainPane.scss b/frontend/src/views/MainPane.scss new file mode 100644 index 0000000..c1a2f7f --- /dev/null +++ b/frontend/src/views/MainPane.scss @@ -0,0 +1,9 @@ +.main-pane { + + .pane { + height: calc(100vh - 210px); + position: relative; + } + + +}
\ No newline at end of file |