From d5ed31be3b6c97f92be4e94b70d32d1b89932ae9 Mon Sep 17 00:00:00 2001 From: Emiliano Ciavatta Date: Wed, 30 Sep 2020 15:58:16 +0200 Subject: Complete services page --- frontend/src/components/panels/RulePane.js | 16 +- frontend/src/components/panels/ServicePane.js | 190 ++++++++++++++++++++++++ frontend/src/components/panels/ServicePane.scss | 22 +++ 3 files changed, 221 insertions(+), 7 deletions(-) create mode 100644 frontend/src/components/panels/ServicePane.js create mode 100644 frontend/src/components/panels/ServicePane.scss (limited to 'frontend/src/components/panels') diff --git a/frontend/src/components/panels/RulePane.js b/frontend/src/components/panels/RulePane.js index d4c5460..7cb849c 100644 --- a/frontend/src/components/panels/RulePane.js +++ b/frontend/src/components/panels/RulePane.js @@ -344,27 +344,29 @@ class RulePane extends Component { filters: this.updateParam((r) => r.filter.service_port = v)} - min={0} max={65565} error={this.state.ruleServicePortError} /> + min={0} max={65565} error={this.state.ruleServicePortError} + readonly={isUpdate} /> this.updateParam((r) => r.filter.client_port = v)} - min={0} max={65565} error={this.state.ruleClientPortError} /> + min={0} max={65565} error={this.state.ruleClientPortError} + readonly={isUpdate} /> this.updateParam((r) => r.filter.client_address = v)} /> this.updateParam((r) => r.filter.min_duration = v)} /> this.updateParam((r) => r.filter.max_duration = v)} /> this.updateParam((r) => r.filter.min_bytes = v)} /> this.updateParam((r) => r.filter.max_bytes = v)} /> diff --git a/frontend/src/components/panels/ServicePane.js b/frontend/src/components/panels/ServicePane.js new file mode 100644 index 0000000..b21ad6c --- /dev/null +++ b/frontend/src/components/panels/ServicePane.js @@ -0,0 +1,190 @@ +import React, {Component} from 'react'; +import './common.scss'; +import './ServicePane.scss'; +import Table from "react-bootstrap/Table"; +import {Col, Container, Row} from "react-bootstrap"; +import InputField from "../fields/InputField"; +import TextField from "../fields/TextField"; +import backend from "../../backend"; +import NumericField from "../fields/extensions/NumericField"; +import ColorField from "../fields/extensions/ColorField"; +import ButtonField from "../fields/ButtonField"; +import validation from "../../validation"; +import LinkPopover from "../objects/LinkPopover"; +import {createCurlCommand} from "../../utils"; + +const classNames = require('classnames'); +const _ = require('lodash'); + +class ServicePane extends Component { + + constructor(props) { + super(props); + + this.state = { + services: [], + currentService: this.emptyService, + }; + } + + componentDidMount() { + this.reset(); + this.loadServices(); + } + + emptyService = { + "port": 0, + "name": "", + "color": "", + "notes": "" + }; + + loadServices = () => { + backend.get("/api/services") + .then(res => this.setState({services: Object.values(res.json), servicesStatusCode: res.status})) + .catch(res => this.setState({servicesStatusCode: res.status, servicesResponse: JSON.stringify(res.json)})); + }; + + updateService = () => { + const service = this.state.currentService; + if (this.validateService(service)) { + backend.put("/api/services", service).then(res => { + this.reset(); + this.setState({serviceStatusCode: res.status}); + this.loadServices(); + }).catch(res => { + this.setState({serviceStatusCode: res.status, serviceResponse: JSON.stringify(res.json)}); + }); + } + }; + + validateService = (service) => { + let valid = true; + if (!validation.isValidPort(service.port, true)) { + this.setState({servicePortError: "port < 0 || port > 65565"}); + valid = false; + } + if (service.name.length < 3) { + this.setState({serviceNameError: "name.length < 3"}); + valid = false; + } + if (!validation.isValidColor(service.color)) { + this.setState({serviceColorError: "color is not hexcolor"}); + valid = false; + } + + return valid; + }; + + reset = () => { + this.setState({ + isUpdate: false, + currentService: _.cloneDeep(this.emptyService), + servicePortError: null, + serviceNameError: null, + serviceColorError: null, + serviceStatusCode: null, + servicesStatusCode: null, + serviceResponse: null, + servicesResponse: null + }); + }; + + updateParam = (callback) => { + callback(this.state.currentService); + this.setState({currentService: this.state.currentService}); + }; + + render() { + const isUpdate = this.state.isUpdate; + const service = this.state.currentService; + + let services = this.state.services.map(s => + { + this.reset(); + this.setState({isUpdate: true, currentService: _.cloneDeep(s)}); + }} className={classNames("row-small", "row-clickable", {"row-selected": service.port === s.port })}> + {s["port"]} + {s["name"]} + + {s["notes"]} + + ); + + const curlCommand = createCurlCommand("/services", "PUT", service); + + return ( +
+
+
+ GET /api/services + {this.state.servicesStatusCode && + } +
+ +
+
+ + + + + + + + + + + {services} + +
portnamecolornotes
+
+
+
+ +
+
+ PUT /api/services + +
+ +
+ + + + this.updateParam((s) => s.port = v)} + min={0} max={65565} error={this.state.servicePortError} /> + this.updateParam((s) => s.name = v)} + error={this.state.serviceNameError} /> + this.updateParam((s) => s.color = v)} /> + + + + this.updateParam((s) => s.notes = v)} /> + + + + + +
+ +
+ {} + +
+
+
+ ); + } + +} + +export default ServicePane; diff --git a/frontend/src/components/panels/ServicePane.scss b/frontend/src/components/panels/ServicePane.scss new file mode 100644 index 0000000..0b154e6 --- /dev/null +++ b/frontend/src/components/panels/ServicePane.scss @@ -0,0 +1,22 @@ + +.service-pane { + display: flex; + flex-direction: column; + + .services-list { + flex: 1; + overflow: hidden; + + .section-content { + height: 100%; + } + + .section-table { + height: calc(100% - 30px); + } + } + + .service-edit { + flex: 0; + } +} -- cgit v1.2.3-70-g09d2