From 6006d47c1f3397862bb13c782d66689067135bdb Mon Sep 17 00:00:00 2001 From: Emiliano Ciavatta Date: Sat, 9 May 2020 14:34:08 +0200 Subject: Add infinite scroll to connections, implement connection actions --- frontend/src/components/Connection.js | 104 +++++++++++++++++++++++---- frontend/src/components/Connection.scss | 26 +++++-- frontend/src/components/ConnectionContent.js | 16 ++--- 3 files changed, 117 insertions(+), 29 deletions(-) (limited to 'frontend/src/components') diff --git a/frontend/src/components/Connection.js b/frontend/src/components/Connection.js index 13b394a..8121d51 100644 --- a/frontend/src/components/Connection.js +++ b/frontend/src/components/Connection.js @@ -1,8 +1,50 @@ import React, {Component} from 'react'; import './Connection.scss'; -import {Button, OverlayTrigger, Tooltip} from "react-bootstrap"; +import axios from 'axios' +import {Button, Form, OverlayTrigger, Popover} from "react-bootstrap"; class Connection extends Component { + + constructor(props) { + super(props); + this.state = { + update: false, + copiedMessage: false + }; + + this.copyTextarea = React.createRef(); + this.handleAction = this.handleAction.bind(this); + } + + handleAction(name) { + if (name === "hide") { + const enabled = !this.props.data.hidden; + axios.post(`/api/connections/${this.props.data.id}/${enabled ? "hide" : "show"}`) + .then(res => { + if (res.status === 202) { + this.props.onEnabled(!enabled); + this.setState({update: true}); + } + }); + } + if (name === "mark") { + const marked = this.props.data.marked; + axios.post(`/api/connections/${this.props.data.id}/${marked ? "unmark" : "mark"}`) + .then(res => { + if (res.status === 202) { + this.props.onMarked(!marked); + this.setState({update: true}); + } + }); + } + if (name === "copy") { + this.copyTextarea.current.select(); + document.execCommand('copy'); + this.setState({copiedMessage: true}); + setTimeout(() => this.setState({copiedMessage: false}), 3000); + } + } + render() { let conn = this.props.data; let serviceName = "/dev/null"; @@ -13,16 +55,37 @@ class Connection extends Component { } let startedAt = new Date(conn.started_at); let closedAt = new Date(conn.closed_at); + let processedAt = new Date(conn.processed_at); let duration = ((closedAt - startedAt) / 1000).toFixed(3); - let timeInfo = `Started at ${startedAt}\nClosed at ${closedAt}\nProcessed at ${new Date(conn.processed_at)}`; + let timeInfo =
+ Started at {startedAt.toLocaleDateString() + " " + startedAt.toLocaleTimeString()}
+ Processed at {processedAt.toLocaleDateString() + " " + processedAt.toLocaleTimeString()}
+ Closed at {closedAt.toLocaleDateString() + " " + closedAt.toLocaleTimeString()} +
; let classes = "connection"; if (this.props.selected) { classes += " connection-selected"; } - if (conn.marked){ - classes += " connection-marked"; - } + + const popoverFor = function (name, content) { + return + + {content} + + ; + }; + + const commentPopoverContent =
+ Click to {conn.comment.length > 0 ? "edit" : "add"} comment + {conn.comment && } +
; + + const copyPopoverContent =
+ {this.state.copiedMessage ? Copied! : + Click to copy the connection id} + +
; return ( @@ -38,24 +101,39 @@ class Connection extends Component { this.props.onSelected()}>{conn.ip_dst} this.props.onSelected()}>{conn.port_dst} this.props.onSelected()}> - {/*{timeInfo}}>*/} + {duration}s - {/**/} + this.props.onSelected()}>{conn.client_bytes} this.props.onSelected()}>{conn.server_bytes} - % - !! - @ - # + Hide this connection from the list)}> + this.handleAction("hide")}>% + + Mark this connection)}> + this.handleAction("mark")}>!! + + + this.handleAction("comment")}>@ + + + this.handleAction("copy")}># + - ); } } - export default Connection; diff --git a/frontend/src/components/Connection.scss b/frontend/src/components/Connection.scss index d27ebc8..5ad195d 100644 --- a/frontend/src/components/Connection.scss +++ b/frontend/src/components/Connection.scss @@ -9,10 +9,6 @@ vertical-align: middle; } - &.connection-marked { - border-right: 5px solid $color-secondary-2; - } - .connection-service { .btn { width: 100%; @@ -31,6 +27,10 @@ cursor: pointer; } + .connection-icon.icon-enabled { + color: $color-secondary-2; + } + &:hover { background-color: $color-primary-2; } @@ -41,3 +41,21 @@ } +.connection-popover { + background-color: $color-primary-4; + border: none; + + .popover-body { + color: $color-primary-1; + + textarea { + background-color: $color-primary-3; + font-size: 12px; + width: 200px; + } + } + + .arrow::after { + border-right-color: $color-primary-4; + } +} diff --git a/frontend/src/components/ConnectionContent.js b/frontend/src/components/ConnectionContent.js index bd35b5c..db63cbe 100644 --- a/frontend/src/components/ConnectionContent.js +++ b/frontend/src/components/ConnectionContent.js @@ -1,18 +1,13 @@ 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'; +import {Dropdown} from 'react-bootstrap'; class ConnectionContent extends Component { render() { - let content = this.props.connectionPayload + let content = this.props.connectionPayload; if (content === undefined) { - return
nope
+ return
nope
; } let payload = content.map(c => @@ -20,10 +15,7 @@ class ConnectionContent extends Component { {c.content} - ) - - - + ); return (
-- cgit v1.2.3-70-g09d2