aboutsummaryrefslogtreecommitdiff
path: root/frontend/src/components/Connection.js
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/src/components/Connection.js')
-rw-r--r--frontend/src/components/Connection.js104
1 files changed, 91 insertions, 13 deletions
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 = <div>
+ <span>Started at {startedAt.toLocaleDateString() + " " + startedAt.toLocaleTimeString()}</span><br/>
+ <span>Processed at {processedAt.toLocaleDateString() + " " + processedAt.toLocaleTimeString()}</span><br/>
+ <span>Closed at {closedAt.toLocaleDateString() + " " + closedAt.toLocaleTimeString()}</span>
+ </div>;
let classes = "connection";
if (this.props.selected) {
classes += " connection-selected";
}
- if (conn.marked){
- classes += " connection-marked";
- }
+
+ const popoverFor = function (name, content) {
+ return <Popover id={`popover-${name}-${conn.id}`} className="connection-popover">
+ <Popover.Content>
+ {content}
+ </Popover.Content>
+ </Popover>;
+ };
+
+ const commentPopoverContent = <div>
+ <span>Click to <strong>{conn.comment.length > 0 ? "edit" : "add"}</strong> comment</span>
+ {conn.comment && <Form.Control as="textarea" readOnly={true} rows={2} defaultValue={conn.comment}/>}
+ </div>;
+
+ const copyPopoverContent = <div>
+ {this.state.copiedMessage ? <span><strong>Copied!</strong></span> :
+ <span>Click to <strong>copy</strong> the connection id</span>}
+ <Form.Control as="textarea" readOnly={true} rows={1} defaultValue={conn.id} ref={this.copyTextarea}/>
+ </div>;
return (
<tr className={classes}>
@@ -38,24 +101,39 @@ class Connection extends Component {
<td className="clickable" onClick={() => this.props.onSelected()}>{conn.ip_dst}</td>
<td className="clickable" onClick={() => this.props.onSelected()}>{conn.port_dst}</td>
<td className="clickable" onClick={() => this.props.onSelected()}>
- {/*<OverlayTrigger placement="top" overlay={<Tooltip id={`tooltip-${conn.id}`}>{timeInfo}</Tooltip>}>*/}
+ <OverlayTrigger trigger={["focus", "hover"]} placement="right"
+ overlay={popoverFor("duration", timeInfo)}>
<span className="test-tooltip">{duration}s</span>
- {/*</OverlayTrigger>*/}
+ </OverlayTrigger>
</td>
<td className="clickable" onClick={() => this.props.onSelected()}>{conn.client_bytes}</td>
<td className="clickable" onClick={() => this.props.onSelected()}>{conn.server_bytes}</td>
<td>
- <span className="connection-icon connection-hide">%</span>
- <span className="connection-icon connection-mark">!!</span>
- <span className="connection-icon connection-comment">@</span>
- <span className="connection-icon connection-link">#</span>
+ <OverlayTrigger trigger={["focus", "hover"]} placement="right"
+ overlay={popoverFor("hide", <span>Hide this connection from the list</span>)}>
+ <span className={"connection-icon" + (conn.hidden ? " icon-enabled" : "")}
+ onClick={() => this.handleAction("hide")}>%</span>
+ </OverlayTrigger>
+ <OverlayTrigger trigger={["focus", "hover"]} placement="right"
+ overlay={popoverFor("hide", <span>Mark this connection</span>)}>
+ <span className={"connection-icon" + (conn.marked ? " icon-enabled" : "")}
+ onClick={() => this.handleAction("mark")}>!!</span>
+ </OverlayTrigger>
+ <OverlayTrigger trigger={["focus", "hover"]} placement="right"
+ overlay={popoverFor("comment", commentPopoverContent)}>
+ <span className={"connection-icon" + (conn.comment ? " icon-enabled" : "")}
+ onClick={() => this.handleAction("comment")}>@</span>
+ </OverlayTrigger>
+ <OverlayTrigger trigger={["focus", "hover"]} placement="right"
+ overlay={popoverFor("copy", copyPopoverContent)}>
+ <span className="connection-icon"
+ onClick={() => this.handleAction("copy")}>#</span>
+ </OverlayTrigger>
</td>
-
</tr>
);
}
}
-
export default Connection;