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