From 9a47e7a2e2100f0bb7ebfab11f7644d32b68241f Mon Sep 17 00:00:00 2001 From: therealbobo Date: Sun, 13 Sep 2020 00:51:39 +0200 Subject: initial commit --- frontend/src/views/Config.js | 226 +++++++++++++++++++++++++++++++++++++++++ frontend/src/views/Config.scss | 38 +++++++ 2 files changed, 264 insertions(+) create mode 100644 frontend/src/views/Config.js create mode 100644 frontend/src/views/Config.scss diff --git a/frontend/src/views/Config.js b/frontend/src/views/Config.js new file mode 100644 index 0000000..438e2d6 --- /dev/null +++ b/frontend/src/views/Config.js @@ -0,0 +1,226 @@ +import { + validateIpAddress, +} from "../utils"; +import React, {Component, useState} from 'react'; +import './Config.scss'; +import {Button, ButtonGroup, ToggleButton, Col, Container, Form, FormControl, InputGroup, Modal, Row, Table} from "react-bootstrap"; +import axios from 'axios' +import {createCurlCommand} from '../utils'; + +class Config extends Component { + + constructor(props) { + super(props); + + this.state = { + server_address: "", + flag_regex: "", + auth_required: false, + accounts: {}, + showSignup: false, + showConfig: true, + tmpUser:"", + tmpPass:"", + tmpConf:"" + }; + + this.serverIpChanged = this.serverIpChanged.bind(this); + this.flagRegexChanged = this.flagRegexChanged.bind(this); + this.authRequiredChanged = this.authRequiredChanged.bind(this); + this.userChanged = this.userChanged.bind(this); + this.passwdChanged = this.passwdChanged.bind(this); + this.confirmChanged = this.confirmChanged.bind(this); + } + + serverIpChanged(event) { + this.setState({server_address: event.target.value}); + } + + flagRegexChanged(event) { + this.setState({flag_regex: event.target.value}); + } + + authRequiredChanged() { + this.setState({auth_required: !this.value}); + this.checked = !this.checked; + this.value = !this.value; + } + + userChanged(event) { + this.setState({tmpUser: event.target.value}); + } + + passwdChanged(event) { + this.setState({tmpPass: event.target.value}); + } + + confirmChanged(event) { + this.setState({tmpConf: event.target.value}); + } + + setup() { + const requestOptions = { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + config: { + server_address: this.state.server_address, + flag_regex: this.state.flag_regex, + auth_required: this.state.auth_required, + }, + accounts: this.state.accounts + }) + }; + + + fetch('/setup', requestOptions) + .then(function(response){ + console.log(response.status); + console.log(response); + } + ); + + } + + signup(){ + if (this.state.tmpPass === this.state.tmpConf){ + const accounts = {...this.state.accounts}; + accounts[this.state.tmpUser] = this.state.tmpPass; + this.setState({accounts}); + console.log(this.state); + this.setState({showSignup:false,showConfig:true}) + } + this.setState({tmpUser : ""}); + this.setState({tmpPass : ""}); + this.setState({tmpConf : ""}); + } + + render() { + let rows = Object.keys(this.state.accounts).map(u => + + {u} + + ); + + + + return ( + <> + + + + # passwd + + + + + +
+ + username: + + + + + password: + + + + + confirm password: + + + + +
+ +
+ +
+
+ + + + + +
+ + + + ~/.config + + + + + + + + + this.authRequiredChanged()} + > + Authentication + + + + + + + + + + + + {rows} + + +
users
+ +
+ + + + + + + +
+ + server_address: + + + + + flag_regex: + + + +
+ + + +
+ +
+
+ + + + +
+ + ); + } +} + +export default Config; diff --git a/frontend/src/views/Config.scss b/frontend/src/views/Config.scss new file mode 100644 index 0000000..9946ce9 --- /dev/null +++ b/frontend/src/views/Config.scss @@ -0,0 +1,38 @@ +@import '../colors.scss'; + +.curl-output { + width: 100%; + font-size: 13px; +} + +#passwd-form { + margin:auto; +} + +.users-list { + .btn { + width: 70px; + } + + td { + background-color: $color-primary-2; + border-top: 2px solid $color-primary-0; + vertical-align: middle; + text-align: center; + } + + th { + background-color: $color-primary-1; + text-align: center; + } +} + +.btn-color { + border: 3px solid #fff; +} + +.dialog-footer { + .btn { + width: 80px; + } +} -- cgit v1.2.3-70-g09d2 From 042cd78894b7c9ce622715e86cb52e203dbe4b34 Mon Sep 17 00:00:00 2001 From: therealbobo Date: Sun, 13 Sep 2020 00:51:55 +0200 Subject: added config menu --- frontend/public/favicon.ico | Bin 3150 -> 34239 bytes frontend/public/logo192.png | Bin 5347 -> 34239 bytes frontend/public/logo512.png | Bin 9664 -> 34239 bytes frontend/src/views/App.js | 11 +++++++++-- frontend/src/views/Header.js | 5 ++--- 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/frontend/public/favicon.ico b/frontend/public/favicon.ico index bcd5dfd..1dc499d 100644 Binary files a/frontend/public/favicon.ico and b/frontend/public/favicon.ico differ diff --git a/frontend/public/logo192.png b/frontend/public/logo192.png index fc44b0a..1dc499d 100644 Binary files a/frontend/public/logo192.png and b/frontend/public/logo192.png differ diff --git a/frontend/public/logo512.png b/frontend/public/logo512.png index a4e47a6..1dc499d 100644 Binary files a/frontend/public/logo512.png and b/frontend/public/logo512.png differ diff --git a/frontend/src/views/App.js b/frontend/src/views/App.js index 6c101fa..229eaed 100644 --- a/frontend/src/views/App.js +++ b/frontend/src/views/App.js @@ -6,6 +6,7 @@ import {BrowserRouter as Router, Route, Switch} from "react-router-dom"; import Services from "./Services"; import Filters from "./Filters"; import Rules from "./Rules"; +import Config from "./Config"; class App extends Component { @@ -14,7 +15,8 @@ class App extends Component { this.state = { servicesWindowOpen: false, filterWindowOpen: false, - rulesWindowOpen: false + rulesWindowOpen: false, + configWindowOpen: false }; } @@ -29,13 +31,18 @@ class App extends Component { if (this.state.rulesWindowOpen) { modal = this.setState({rulesWindowOpen: false})}/>; } + if (this.state.configWindowOpen) { + modal = this.setState({configWindowOpen: false})}/>; + } return (
this.setState({servicesWindowOpen: true})} onOpenFilters={() => this.setState({filterWindowOpen: true})} - onOpenRules={() => this.setState({rulesWindowOpen: true})} /> + onOpenRules={() => this.setState({rulesWindowOpen: true})} + onOpenConfig={() => this.setState({configWindowOpen: true})} + /> }/> }/> diff --git a/frontend/src/views/Header.js b/frontend/src/views/Header.js index 5d0f690..03e4e5c 100644 --- a/frontend/src/views/Header.js +++ b/frontend/src/views/Header.js @@ -72,9 +72,8 @@ class Header extends Component { - + +
-- cgit v1.2.3-70-g09d2 From fdf53489eced715e1586f582882cb064721a965e Mon Sep 17 00:00:00 2001 From: therealbobo Date: Sun, 13 Sep 2020 12:07:11 +0200 Subject: service creation/edit fix --- frontend/src/views/Services.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/frontend/src/views/Services.js b/frontend/src/views/Services.js index b95b01c..9f0fbd2 100644 --- a/frontend/src/views/Services.js +++ b/frontend/src/views/Services.js @@ -64,12 +64,33 @@ class Services extends Component { saveService() { if (this.state.portValid && this.state.nameValid) { + const requestOptions = { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + color: this.state.color, + name: this.state.name, + notes: this.state.notes, + port: this.state.port, + }) + }; + + + fetch('/api/services', requestOptions) + .then(function(response){ + console.log(response); + } + ); + + /* axios.put("/api/services", { name: this.state.name, port: this.state.port, color: this.state.color, notes: this.state.notes }); + */ + this.newService(); this.loadServices(); -- cgit v1.2.3-70-g09d2 From b5f3cd7accf3699fd7ed3053d671a4c254dfeaa3 Mon Sep 17 00:00:00 2001 From: therealbobo Date: Mon, 14 Sep 2020 09:45:18 +0200 Subject: auto startup configuration --- frontend/src/views/App.js | 9 +++++++++ frontend/src/views/Config.js | 9 +++++---- frontend/src/views/Services.js | 10 ---------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/frontend/src/views/App.js b/frontend/src/views/App.js index 229eaed..5b49045 100644 --- a/frontend/src/views/App.js +++ b/frontend/src/views/App.js @@ -18,6 +18,15 @@ class App extends Component { rulesWindowOpen: false, configWindowOpen: false }; + + fetch('/api/services') + .then(response => { + if( response.status === 503){ + this.setState({configWindowOpen: true}); + } + }); + + } render() { diff --git a/frontend/src/views/Config.js b/frontend/src/views/Config.js index 438e2d6..9b220d9 100644 --- a/frontend/src/views/Config.js +++ b/frontend/src/views/Config.js @@ -4,7 +4,6 @@ import { import React, {Component, useState} from 'react'; import './Config.scss'; import {Button, ButtonGroup, ToggleButton, Col, Container, Form, FormControl, InputGroup, Modal, Row, Table} from "react-bootstrap"; -import axios from 'axios' import {createCurlCommand} from '../utils'; class Config extends Component { @@ -74,9 +73,11 @@ class Config extends Component { fetch('/setup', requestOptions) - .then(function(response){ - console.log(response.status); - console.log(response); + .then(response => { + if (response.status === 202 ){ + //this.setState({showConfig:false}); + this.props.onHide(); + } } ); diff --git a/frontend/src/views/Services.js b/frontend/src/views/Services.js index 9f0fbd2..0de021f 100644 --- a/frontend/src/views/Services.js +++ b/frontend/src/views/Services.js @@ -82,16 +82,6 @@ class Services extends Component { } ); - /* - axios.put("/api/services", { - name: this.state.name, - port: this.state.port, - color: this.state.color, - notes: this.state.notes - }); - */ - - this.newService(); this.loadServices(); } -- cgit v1.2.3-70-g09d2 From e1ce4fefede7f956e4b7ae9bc602b4f49fbfad69 Mon Sep 17 00:00:00 2001 From: therealbobo Date: Mon, 14 Sep 2020 11:32:57 +0200 Subject: auto disabling config button --- frontend/src/views/App.js | 9 +++++++-- frontend/src/views/Config.js | 4 ++++ frontend/src/views/Config.scss | 13 +++++++++++++ frontend/src/views/Header.js | 3 ++- 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/frontend/src/views/App.js b/frontend/src/views/App.js index 5b49045..5a2d913 100644 --- a/frontend/src/views/App.js +++ b/frontend/src/views/App.js @@ -16,13 +16,16 @@ class App extends Component { servicesWindowOpen: false, filterWindowOpen: false, rulesWindowOpen: false, - configWindowOpen: false + configWindowOpen: false, + configDone: false }; fetch('/api/services') .then(response => { if( response.status === 503){ this.setState({configWindowOpen: true}); + } else if (response.status === 200){ + this.setState({configDone: true}); } }); @@ -41,7 +44,8 @@ class App extends Component { modal = this.setState({rulesWindowOpen: false})}/>; } if (this.state.configWindowOpen) { - modal = this.setState({configWindowOpen: false})}/>; + modal = this.setState({configWindowOpen: false})} + onDone={() => this.setState({configDone: true})}/>; } return ( @@ -51,6 +55,7 @@ class App extends Component { onOpenFilters={() => this.setState({filterWindowOpen: true})} onOpenRules={() => this.setState({rulesWindowOpen: true})} onOpenConfig={() => this.setState({configWindowOpen: true})} + onConfigDone={this.state.configDone} /> }/> diff --git a/frontend/src/views/Config.js b/frontend/src/views/Config.js index 9b220d9..1468b1b 100644 --- a/frontend/src/views/Config.js +++ b/frontend/src/views/Config.js @@ -77,6 +77,8 @@ class Config extends Component { if (response.status === 202 ){ //this.setState({showConfig:false}); this.props.onHide(); + this.props.onDone(); + console.log(this.props.disabled); } } ); @@ -158,6 +160,8 @@ class Config extends Component { + +
diff --git a/frontend/src/views/Config.scss b/frontend/src/views/Config.scss index 9946ce9..b0b899f 100644 --- a/frontend/src/views/Config.scss +++ b/frontend/src/views/Config.scss @@ -36,3 +36,16 @@ width: 80px; } } + +.blink{ + + span{ + animation: blink 1s linear infinite; + } + @keyframes blink{ + 0%{opacity: 0;} + 50%{opacity: .5;} + 100%{opacity: 1;} + } + +} diff --git a/frontend/src/views/Header.js b/frontend/src/views/Header.js index 03e4e5c..3f95bcd 100644 --- a/frontend/src/views/Header.js +++ b/frontend/src/views/Header.js @@ -73,7 +73,8 @@ class Header extends Component { - + -- cgit v1.2.3-70-g09d2 From 83a5fedb95ea211f3bd66ab94d87e82ee1cc51e3 Mon Sep 17 00:00:00 2001 From: therealbobo Date: Mon, 14 Sep 2020 12:11:45 +0200 Subject: added error handling --- frontend/src/views/Config.js | 21 +++++++++++++++++++-- frontend/src/views/Config.scss | 4 ++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/frontend/src/views/Config.js b/frontend/src/views/Config.js index 1468b1b..f5766eb 100644 --- a/frontend/src/views/Config.js +++ b/frontend/src/views/Config.js @@ -20,7 +20,8 @@ class Config extends Component { showConfig: true, tmpUser:"", tmpPass:"", - tmpConf:"" + tmpConf:"", + errors:"" }; this.serverIpChanged = this.serverIpChanged.bind(this); @@ -71,6 +72,7 @@ class Config extends Component { }) }; + let msg = ""; fetch('/setup', requestOptions) .then(response => { @@ -78,7 +80,12 @@ class Config extends Component { //this.setState({showConfig:false}); this.props.onHide(); this.props.onDone(); - console.log(this.props.disabled); + } else { + response.json().then(data => { + this.setState( + {errors : data.error.toString()} + ); + }); } } ); @@ -215,6 +222,16 @@ class Config extends Component { + +
+ + {this.state.errors + .split('\n').map((item, key) => { + return {item}
}) + } +
+
+
diff --git a/frontend/src/views/Config.scss b/frontend/src/views/Config.scss index b0b899f..331d7a7 100644 --- a/frontend/src/views/Config.scss +++ b/frontend/src/views/Config.scss @@ -49,3 +49,7 @@ } } + +.error{ + color: red; +} -- cgit v1.2.3-70-g09d2 From 9c43baa03012d1ef8228cd70c479bd956df61321 Mon Sep 17 00:00:00 2001 From: therealbobo Date: Mon, 14 Sep 2020 18:48:35 +0200 Subject: added bs-custom-file-input --- frontend/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/package.json b/frontend/package.json index 661c2c4..bf995c5 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -11,6 +11,7 @@ "@testing-library/user-event": "^7.1.2", "axios": "^0.19.2", "bootstrap": "^4.4.1", + "bs-custom-file-input": "^1.3.4", "classnames": "^2.2.6", "eslint-config-react-app": "^5.2.1", "node-sass": "^4.14.0", -- cgit v1.2.3-70-g09d2 From 08e02ba4c3dd136897f058587f4c4e0a79be99e3 Mon Sep 17 00:00:00 2001 From: therealbobo Date: Mon, 14 Sep 2020 18:48:42 +0200 Subject: added bs-custom-file-input --- frontend/yarn.lock | 421 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 242 insertions(+), 179 deletions(-) diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 64061b5..7517add 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -48,18 +48,18 @@ source-map "^0.5.0" "@babel/core@^7.1.0", "@babel/core@^7.4.5": - version "7.11.4" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.11.4.tgz#4301dfdfafa01eeb97f1896c5501a3f0655d4229" - integrity sha512-5deljj5HlqRXN+5oJTY7Zs37iH3z3b++KjiKtIsJy1NrjOOVSEaJHEetLBhyu0aQOSNNZ/0IuEAan9GzRuDXHg== + version "7.11.6" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.11.6.tgz#3a9455dc7387ff1bac45770650bc13ba04a15651" + integrity sha512-Wpcv03AGnmkgm6uS6k8iwhIwTrcP0m17TL1n1sy7qD0qelDu4XNeW0dN0mHfa+Gei211yDaLoEe/VlbXQzM4Bg== dependencies: "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.11.4" + "@babel/generator" "^7.11.6" "@babel/helper-module-transforms" "^7.11.0" "@babel/helpers" "^7.10.4" - "@babel/parser" "^7.11.4" + "@babel/parser" "^7.11.5" "@babel/template" "^7.10.4" - "@babel/traverse" "^7.11.0" - "@babel/types" "^7.11.0" + "@babel/traverse" "^7.11.5" + "@babel/types" "^7.11.5" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.1" @@ -69,12 +69,12 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.11.0", "@babel/generator@^7.11.4", "@babel/generator@^7.4.0", "@babel/generator@^7.9.0": - version "7.11.4" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.11.4.tgz#1ec7eec00defba5d6f83e50e3ee72ae2fee482be" - integrity sha512-Rn26vueFx0eOoz7iifCN2UHT6rGtnkSGWSoDRIy8jZN3B91PzeSULbswfLoOWuTuAcNwpG/mxy+uCTDnZ9Mp1g== +"@babel/generator@^7.11.5", "@babel/generator@^7.11.6", "@babel/generator@^7.4.0", "@babel/generator@^7.9.0": + version "7.11.6" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.11.6.tgz#b868900f81b163b4d464ea24545c61cbac4dc620" + integrity sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA== dependencies: - "@babel/types" "^7.11.0" + "@babel/types" "^7.11.5" jsesc "^2.5.1" source-map "^0.5.0" @@ -93,14 +93,14 @@ "@babel/helper-explode-assignable-expression" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/helper-builder-react-jsx-experimental@^7.10.4": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.10.5.tgz#f35e956a19955ff08c1258e44a515a6d6248646b" - integrity sha512-Buewnx6M4ttG+NLkKyt7baQn7ScC/Td+e99G914fRU8fGIUivDDgVIQeDHFa5e4CRSJQt58WpNHhsAZgtzVhsg== +"@babel/helper-builder-react-jsx-experimental@^7.10.4", "@babel/helper-builder-react-jsx-experimental@^7.11.5": + version "7.11.5" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.11.5.tgz#4ea43dd63857b0a35cd1f1b161dc29b43414e79f" + integrity sha512-Vc4aPJnRZKWfzeCBsqTBnzulVNjABVdahSPhtdMD3Vs80ykx4a87jTHtF/VR+alSrDmNvat7l13yrRHauGcHVw== dependencies: "@babel/helper-annotate-as-pure" "^7.10.4" "@babel/helper-module-imports" "^7.10.4" - "@babel/types" "^7.10.5" + "@babel/types" "^7.11.5" "@babel/helper-builder-react-jsx@^7.10.4": version "7.10.4" @@ -302,10 +302,10 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.10.4", "@babel/parser@^7.11.0", "@babel/parser@^7.11.4", "@babel/parser@^7.4.3", "@babel/parser@^7.7.0", "@babel/parser@^7.9.0": - version "7.11.4" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.4.tgz#6fa1a118b8b0d80d0267b719213dc947e88cc0ca" - integrity sha512-MggwidiH+E9j5Sh8pbrX5sJvMcsqS5o+7iB42M9/k0CD63MjYbdP4nhSh7uB5wnv2/RVzTZFTxzF/kIa5mrCqA== +"@babel/parser@^7.1.0", "@babel/parser@^7.10.4", "@babel/parser@^7.11.5", "@babel/parser@^7.4.3", "@babel/parser@^7.7.0", "@babel/parser@^7.9.0": + version "7.11.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.5.tgz#c7ff6303df71080ec7a4f5b8c003c58f1cf51037" + integrity sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q== "@babel/plugin-proposal-async-generator-functions@^7.10.4", "@babel/plugin-proposal-async-generator-functions@^7.8.3": version "7.10.5" @@ -781,11 +781,11 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-react-jsx-development@^7.10.4", "@babel/plugin-transform-react-jsx-development@^7.9.0": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.10.4.tgz#6ec90f244394604623880e15ebc3c34c356258ba" - integrity sha512-RM3ZAd1sU1iQ7rI2dhrZRZGv0aqzNQMbkIUCS1txYpi9wHQ2ZHNjo5TwX+UD6pvFW4AbWqLVYvKy5qJSAyRGjQ== + version "7.11.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.11.5.tgz#e1439e6a57ee3d43e9f54ace363fb29cefe5d7b6" + integrity sha512-cImAmIlKJ84sDmpQzm4/0q/2xrXlDezQoixy3qoz1NJeZL/8PRon6xZtluvr4H4FzwlDGI5tCcFupMnXGtr+qw== dependencies: - "@babel/helper-builder-react-jsx-experimental" "^7.10.4" + "@babel/helper-builder-react-jsx-experimental" "^7.11.5" "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-jsx" "^7.10.4" @@ -976,9 +976,9 @@ semver "^5.5.0" "@babel/preset-env@^7.4.5": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.11.0.tgz#860ee38f2ce17ad60480c2021ba9689393efb796" - integrity sha512-2u1/k7rG/gTh02dylX2kL3S0IJNF+J6bfDSp4DI2Ma8QN6Y9x9pmAax59fsCk6QUQG0yqH47yJWA+u1I1LccAg== + version "7.11.5" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.11.5.tgz#18cb4b9379e3e92ffea92c07471a99a2914e4272" + integrity sha512-kXqmW1jVcnB2cdueV+fyBM8estd5mlNfaQi6lwLgRwCby4edpavgbFhiBNjmWA3JpB/yZGSISa7Srf+TwxDQoA== dependencies: "@babel/compat-data" "^7.11.0" "@babel/helper-compilation-targets" "^7.10.4" @@ -1042,7 +1042,7 @@ "@babel/plugin-transform-unicode-escapes" "^7.10.4" "@babel/plugin-transform-unicode-regex" "^7.10.4" "@babel/preset-modules" "^0.1.3" - "@babel/types" "^7.11.0" + "@babel/types" "^7.11.5" browserslist "^4.12.0" core-js-compat "^3.6.2" invariant "^2.2.2" @@ -1050,9 +1050,9 @@ semver "^5.5.0" "@babel/preset-modules@^0.1.3": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.3.tgz#13242b53b5ef8c883c3cf7dddd55b36ce80fbc72" - integrity sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg== + version "0.1.4" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.4.tgz#362f2b68c662842970fdb5e254ffc8fc1c2e415e" + integrity sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" @@ -1124,25 +1124,25 @@ "@babel/parser" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/traverse@^7.1.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.11.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.7.0", "@babel/traverse@^7.9.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.11.0.tgz#9b996ce1b98f53f7c3e4175115605d56ed07dd24" - integrity sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg== +"@babel/traverse@^7.1.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.11.5", "@babel/traverse@^7.4.3", "@babel/traverse@^7.7.0", "@babel/traverse@^7.9.0": + version "7.11.5" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.11.5.tgz#be777b93b518eb6d76ee2e1ea1d143daa11e61c3" + integrity sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ== dependencies: "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.11.0" + "@babel/generator" "^7.11.5" "@babel/helper-function-name" "^7.10.4" "@babel/helper-split-export-declaration" "^7.11.0" - "@babel/parser" "^7.11.0" - "@babel/types" "^7.11.0" + "@babel/parser" "^7.11.5" + "@babel/types" "^7.11.5" debug "^4.1.0" globals "^11.1.0" lodash "^4.17.19" -"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.7.0", "@babel/types@^7.9.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.0.tgz#2ae6bf1ba9ae8c3c43824e5861269871b206e90d" - integrity sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA== +"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.11.5", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.7.0", "@babel/types@^7.9.0": + version "7.11.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.5.tgz#d9de577d01252d77c6800cee039ee64faf75662d" + integrity sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q== dependencies: "@babel/helper-validator-identifier" "^7.10.4" lodash "^4.17.19" @@ -1382,6 +1382,17 @@ "@types/yargs" "^15.0.0" chalk "^3.0.0" +"@jest/types@^26.3.0": + version "26.3.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.3.0.tgz#97627bf4bdb72c55346eef98e3b3f7ddc4941f71" + integrity sha512-BDPG23U0qDeAvU4f99haztXwdAg3hz4El95LkAM+tHAqqhiVzRpEGHHU8EDxT/AnxOrA65YjLBwDahdJ9pTLJQ== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^15.0.0" + chalk "^4.0.0" + "@mrmlnc/readdir-enhanced@^2.2.1": version "2.2.1" resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" @@ -1522,15 +1533,17 @@ loader-utils "^1.2.3" "@testing-library/dom@*": - version "7.22.3" - resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-7.22.3.tgz#12c0b1b97115e7731da6a86b4574eae401cb9ac5" - integrity sha512-IK6/eL1Xza/0goDKrwnBvlM06L+5eL9b1o+hUhX7HslfUvMETh0TYgXEr2LVpsVkHiOhRmUbUyml95KV/VlRNw== + version "7.24.2" + resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-7.24.2.tgz#6d2b7dd21efbd5358b98c2777fc47c252f3ae55e" + integrity sha512-ERxcZSoHx0EcN4HfshySEWmEf5Kkmgi+J7O79yCJ3xggzVlBJ2w/QjJUC+EBkJJ2OeSw48i3IoePN4w8JlVUIA== dependencies: + "@babel/code-frame" "^7.10.4" "@babel/runtime" "^7.10.3" "@types/aria-query" "^4.2.0" aria-query "^4.2.2" + chalk "^4.1.0" dom-accessibility-api "^0.5.1" - pretty-format "^25.5.0" + pretty-format "^26.4.2" "@testing-library/dom@^6.15.0": version "6.16.0" @@ -1606,9 +1619,9 @@ "@babel/types" "^7.0.0" "@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": - version "7.0.13" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.0.13.tgz#1874914be974a492e1b4cb00585cabb274e8ba18" - integrity sha512-i+zS7t6/s9cdQvbqKDARrcbrPvtJGlbYsMkazo03nTAK3RX9FNrLllXys22uiTGJapPOTZTQ35nHh4ISph4SLQ== + version "7.0.14" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.0.14.tgz#e99da8c075d4fb098c774ba65dabf7dc9954bd13" + integrity sha512-8w9szzKs14ZtBVuP6Wn7nMLRJ0D6dfB0VEBEyRgxrZ/Ln49aNMykrghM2FaNn4FJRzNppCSa0Rv9pBRM5Xc3wg== dependencies: "@babel/types" "^7.3.0" @@ -1636,9 +1649,9 @@ "@types/node" "*" "@types/invariant@^2.2.33": - version "2.2.33" - resolved "https://registry.yarnpkg.com/@types/invariant/-/invariant-2.2.33.tgz#ec5eec29c63bf5e4ca164e9feb3ef7337cdcbadb" - integrity sha512-/jUNmS8d4bCKdqslfxW6dg/9Gksfzxz67IYfqApHn+HvHlMVXwYv2zpTDnS/yaK9BB0i0GlBTaYci0EFE62Hmw== + version "2.2.34" + resolved "https://registry.yarnpkg.com/@types/invariant/-/invariant-2.2.34.tgz#05e4f79f465c2007884374d4795452f995720bbe" + integrity sha512-lYUtmJ9BqUN688fGY1U1HZoWT1/Jrmgigx2loq4ZcJpICECm/Om3V314BxdzypO0u5PORKGMM6x0OXaljV1YFg== "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": version "2.0.3" @@ -1660,10 +1673,17 @@ "@types/istanbul-lib-coverage" "*" "@types/istanbul-lib-report" "*" -"@types/json-schema@^7.0.3", "@types/json-schema@^7.0.4": - version "7.0.5" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.5.tgz#dcce4430e64b443ba8945f0290fb564ad5bac6dd" - integrity sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ== +"@types/istanbul-reports@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.0.tgz#508b13aa344fa4976234e75dddcc34925737d821" + integrity sha512-nwKNbvnwJ2/mndE9ItP/zc2TCzw6uuodnF4EHYWD+gCQDVBuRQL5UzbZD0/ezy1iKsFU2ZQiDqg4M9dN4+wZgA== + dependencies: + "@types/istanbul-lib-report" "*" + +"@types/json-schema@^7.0.3", "@types/json-schema@^7.0.5": + version "7.0.6" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0" + integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw== "@types/minimatch@*": version "3.0.3" @@ -1671,9 +1691,9 @@ integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== "@types/node@*": - version "14.6.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.6.0.tgz#7d4411bf5157339337d7cff864d9ff45f177b499" - integrity sha512-mikldZQitV94akrc4sCcSjtJfsTKt4p+e/s0AGscVA6XArQ9kFclP+ZiYUMnq987rc6QlYxXv/EivqlfSLxpKA== + version "14.10.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.10.1.tgz#cc323bad8e8a533d4822f45ce4e5326f36e42177" + integrity sha512-aYNbO+FZ/3KGeQCEkNhHFRIzBOUgc7QvcVNKXbfnhDkSfwUv91JsQQa10rDgKSTSLkXZ1UIyPe4FJJNVgw1xWQ== "@types/parse-json@^4.0.0": version "4.0.0" @@ -1705,9 +1725,9 @@ "@types/react" "*" "@types/react@*", "@types/react@^16.9.11", "@types/react@^16.9.35": - version "16.9.46" - resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.46.tgz#f0326cd7adceda74148baa9bff6e918632f5069e" - integrity sha512-dbHzO3aAq1lB3jRQuNpuZ/mnu+CdD3H0WVaaBQA8LTT3S33xhVBUj232T8M3tAhSWJs/D/UqORYUlJNl/8VQZg== + version "16.9.49" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.49.tgz#09db021cf8089aba0cdb12a49f8021a69cce4872" + integrity sha512-DtLFjSj0OYAdVLBbyjhuV9CdGVHCkHn2R+xr3XkBvK2rS1Y1tkc14XSGjYgm5Fjjr90AxH9tiSzc1pCFMGO06g== dependencies: "@types/prop-types" "*" csstype "^3.0.2" @@ -1964,9 +1984,9 @@ integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== abab@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.4.tgz#6dfa57b417ca06d21b2478f0e638302f99c2405c" - integrity sha512-Eu9ELJWCz/c1e9gTiCY+FceWxcqzjYEbqMgtndnuSqZSUCOL73TWNK2mHfIj4Cw2E/ongOp+JISVNCmovt2KYQ== + version "2.0.5" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" + integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q== abbrev@1: version "1.1.1" @@ -1990,9 +2010,9 @@ acorn-globals@^4.1.0, acorn-globals@^4.3.0: acorn-walk "^6.0.1" acorn-jsx@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.2.0.tgz#4c66069173d6fdd68ed85239fc256226182b2ebe" - integrity sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ== + version "5.3.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" + integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== acorn-walk@^6.0.1: version "6.2.0" @@ -2031,9 +2051,9 @@ adjust-sourcemap-loader@2.0.0: regex-parser "2.2.10" aggregate-error@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.0.1.tgz#db2fe7246e536f40d9b5442a39e117d7dd6a24e0" - integrity sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA== + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== dependencies: clean-stack "^2.0.0" indent-string "^4.0.0" @@ -2043,15 +2063,15 @@ ajv-errors@^1.0.0: resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== -ajv-keywords@^3.1.0, ajv-keywords@^3.4.1: +ajv-keywords@^3.1.0, ajv-keywords@^3.4.1, ajv-keywords@^3.5.2: version "3.5.2" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== -ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.2, ajv@^6.12.3: - version "6.12.4" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.4.tgz#0614facc4522127fa713445c6bfd3ebd376e2234" - integrity sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ== +ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4: + version "6.12.5" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.5.tgz#19b0e8bae8f476e5ba666300387775fb1a00a4da" + integrity sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag== dependencies: fast-deep-equal "^3.1.1" fast-json-stable-stringify "^2.0.0" @@ -2772,14 +2792,19 @@ browserslist@4.10.0: pkg-up "^3.1.0" browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.6.2, browserslist@^4.6.4, browserslist@^4.8.5, browserslist@^4.9.1: - version "4.14.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.0.tgz#2908951abfe4ec98737b72f34c3bcedc8d43b000" - integrity sha512-pUsXKAF2lVwhmtpeA3LJrZ76jXuusrNyhduuQs7CDFf9foT4Y38aQOserd2lMe5DSSrjf3fx34oHwryuvxAUgQ== + version "4.14.2" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.2.tgz#1b3cec458a1ba87588cc5e9be62f19b6d48813ce" + integrity sha512-HI4lPveGKUR0x2StIz+2FXfDk9SfVMrxn6PLh1JeGUwcuoDkdKZebWiyLRJ68iIPDpMI4JLVDf7S7XzslgWOhw== dependencies: - caniuse-lite "^1.0.30001111" - electron-to-chromium "^1.3.523" + caniuse-lite "^1.0.30001125" + electron-to-chromium "^1.3.564" escalade "^3.0.2" - node-releases "^1.1.60" + node-releases "^1.1.61" + +bs-custom-file-input@^1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/bs-custom-file-input/-/bs-custom-file-input-1.3.4.tgz#c275cb8d4f1c02ba026324292509fa9a747dbda8" + integrity sha512-NBsQzTnef3OW1MvdKBbMHAYHssCd613MSeJV7z2McXznWtVMnJCy7Ckyc+PwxV6Pk16cu6YBcYWh/ZE0XWNKCA== bser@2.1.1: version "2.1.1" @@ -2957,10 +2982,10 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001035, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001111: - version "1.0.30001117" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001117.tgz#69a9fae5d480eaa9589f7641a83842ad396d17c4" - integrity sha512-4tY0Fatzdx59kYjQs+bNxUwZB03ZEBgVmJ1UkFPz/Q8OLiUUbjct2EdpnXj0fvFTPej2EkbPIG0w8BWsjAyk1Q== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001035, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001125: + version "1.0.30001129" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001129.tgz#e6514b94c0ef50f98cf7476daa91228ddd2ef7bc" + integrity sha512-9945fTVKS810DZITpsAbuhQG7Lam0tEfVbZlsBaCFZaszepbryrArS05PWmJSBQ6mta+v9iz0pUIAbW1eBILIg== capture-exit@^2.0.0: version "2.0.0" @@ -3007,7 +3032,7 @@ chalk@^3.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^4.1.0: +chalk@^4.0.0, chalk@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== @@ -3735,9 +3760,9 @@ cssstyle@^1.0.0, cssstyle@^1.1.1: cssom "0.3.x" csstype@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.2.tgz#ee5ff8f208c8cd613b389f7b222c9801ca62b3f7" - integrity sha512-ofovWglpqoqbfLNOTBNZLSbMuGrblAf1efvvArGKOZMBrIoJeu5UsAipQolkijtyQx5MtAzT/J9IHj/CEY1mJw== + version "3.0.3" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.3.tgz#2b410bbeba38ba9633353aff34b05d9755d065f8" + integrity sha512-jPl+wbWPOWJ7SXsWyqGRk3lGecbar0Cb0OvZF/r/ZU011R4YqiRehgkQ9p4eQfo9DSDLqLL3wHwfxeJiuIsNag== currently-unhandled@^0.4.1: version "0.4.1" @@ -4001,9 +4026,9 @@ dom-accessibility-api@^0.3.0: integrity sha512-PzwHEmsRP3IGY4gv/Ug+rMeaTIyTJvadCb+ujYXYeIylbHJezIyNToe8KfEgHTCEYyC+/bUghYOGg8yMGlZ6vA== dom-accessibility-api@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.1.tgz#152f5e88583d900977119223e3e76c2d93d23830" - integrity sha512-8DhtmKTYWXNpPiL/QOszbnkAbCGuPz9ieVwDrmWM1rNx4KRI3zqmvKANAD1PJdvvov3+eq1BPLXQkYTpqTrWng== + version "0.5.2" + resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.2.tgz#ef3cdb5d3f0d599d8f9c8b18df2fb63c9793739d" + integrity sha512-k7hRNKAiPJXD2aBqfahSo4/01cTsKWXf+LqJgglnkN2Nz8TsxXKQBXHhKe0Ye9fEfHEZY49uSA5Sr3AqP/sWKA== dom-converter@^0.2: version "0.2.0" @@ -4039,9 +4064,9 @@ domelementtype@1, domelementtype@^1.3.1: integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== domelementtype@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d" - integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ== + version "2.0.2" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.2.tgz#f3b6e549201e46f588b59463dd77187131fe6971" + integrity sha512-wFwTwCVebUrMgGeAwRL/NhZtHAUyT9n9yg4IMDwf10+6iCMxSkVq9MGCVEH+QZWo1nNidy8kNvwmv4zWHDTqvA== domexception@^1.0.1: version "1.0.1" @@ -4082,9 +4107,9 @@ dot-case@^3.0.3: tslib "^1.10.0" dot-prop@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.2.0.tgz#c34ecc29556dc45f1f4c22697b6f4904e0cc4fcb" - integrity sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A== + version "5.3.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" + integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q== dependencies: is-obj "^2.0.0" @@ -4126,10 +4151,10 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= -electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.523: - version "1.3.540" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.540.tgz#4e4c08d8c12bbd32cf090e143c0d546f017f9d43" - integrity sha512-IoGiZb8SMqTtkDYJtP8EtCdvv3VMtd1QoTlypO2RUBxRq/Wk0rU5IzhzhMckPaC9XxDqUvWsL0XKOBhTiYVN3w== +electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.564: + version "1.3.567" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.567.tgz#7a404288952ac990e447a7a86470d460ea953b8f" + integrity sha512-1aKkw0Hha1Bw9JA5K5PT5eFXC/TXbkJvUfNSNEciPUMgSIsRJZM1hF2GUEAGZpAbgvd8En21EA+Lv820KOhvqA== elliptic@^6.5.3: version "6.5.3" @@ -4226,6 +4251,24 @@ es-abstract@^1.17.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstrac string.prototype.trimend "^1.0.1" string.prototype.trimstart "^1.0.1" +es-abstract@^1.18.0-next.0: + version "1.18.0-next.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.0.tgz#b302834927e624d8e5837ed48224291f2c66e6fc" + integrity sha512-elZXTZXKn51hUBdJjSZGYRujuzilgXo8vSPQzjGYXLvSlGiCo8VO8ZGV3kjo9a0WNJJ57hENagwbtlRuHuzkcQ== + dependencies: + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.2.0" + is-negative-zero "^2.0.0" + is-regex "^1.1.1" + object-inspect "^1.8.0" + object-keys "^1.1.1" + object.assign "^4.1.0" + string.prototype.trimend "^1.0.1" + string.prototype.trimstart "^1.0.1" + es-to-primitive@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" @@ -4399,11 +4442,11 @@ eslint-scope@^4.0.3: estraverse "^4.1.1" eslint-scope@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.0.tgz#d0f971dfe59c69e0cada684b23d49dbf82600ce5" - integrity sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w== + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== dependencies: - esrecurse "^4.1.0" + esrecurse "^4.3.0" estraverse "^4.1.1" eslint-utils@^1.4.3: @@ -4489,19 +4532,19 @@ esquery@^1.0.1: dependencies: estraverse "^5.1.0" -esrecurse@^4.1.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" - integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== +esrecurse@^4.1.0, esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== dependencies: - estraverse "^4.1.0" + estraverse "^5.2.0" -estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: +estraverse@^4.1.1, estraverse@^4.2.0: version "4.3.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== -estraverse@^5.1.0: +estraverse@^5.1.0, estraverse@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== @@ -4517,9 +4560,9 @@ etag@~1.8.1: integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= eventemitter3@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384" - integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== + version "4.0.7" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" + integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== events@^3.0.0: version "3.2.0" @@ -5269,7 +5312,7 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-symbols@^1.0.0, has-symbols@^1.0.1: +has-symbols@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== @@ -5816,9 +5859,9 @@ is-buffer@^1.0.2, is-buffer@^1.1.5: integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== is-callable@^1.1.4, is-callable@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.0.tgz#83336560b54a38e35e3a2df7afd0454d691468bb" - integrity sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw== + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.1.tgz#4d1e21a4f437509d25ce55f8184350771421c96d" + integrity sha512-wliAfSzx6V+6WfMOmus1xy0XvSgf/dlStkvTfq7F0g4bOIW0PSUbnyse3NhDwdyYS1ozfUtAAySqTws3z9Eqgg== is-ci@^2.0.0: version "2.0.0" @@ -5944,6 +5987,11 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" +is-negative-zero@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.0.tgz#9553b121b0fac28869da9ed459e20c7543788461" + integrity sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE= + is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" @@ -5997,7 +6045,7 @@ is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" -is-regex@^1.0.4, is-regex@^1.1.0: +is-regex@^1.0.4, is-regex@^1.1.0, is-regex@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.1.tgz#c6f98aacc546f6cec5468a07b7b153ab564a57b9" integrity sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg== @@ -6641,6 +6689,11 @@ json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" @@ -6944,9 +6997,9 @@ lodash.uniq@^4.5.0: integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== loglevel@^1.6.6: - version "1.6.8" - resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.8.tgz#8a25fb75d092230ecd4457270d80b54e28011171" - integrity sha512-bsU7+gc9AJ2SqpzxwU3+1fedl8zAntbtC5XYlt3s2j1hJcn2PsXSmgN8TaLG/J1/2mod4+cE/3vNL70/c1RNCA== + version "1.7.0" + resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.7.0.tgz#728166855a740d59d38db01cf46f042caa041bb0" + integrity sha512-i2sY04nal5jDcagM3FMfG++T69GEEM8CYuOfeOIvmXzOIcwE9a/CJPR0MFM97pYMj/u10lzz7/zd7+qwhrBTqQ== loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0: version "1.4.0" @@ -7474,10 +7527,10 @@ node-notifier@^5.4.2: shellwords "^0.1.1" which "^1.3.0" -node-releases@^1.1.52, node-releases@^1.1.60: - version "1.1.60" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.60.tgz#6948bdfce8286f0b5d0e5a88e8384e954dfe7084" - integrity sha512-gsO4vjEdQaTusZAEebUWp2a5d7dF5DYoIpDG7WySnk7BuZDW+GPpHXoXXuYawRBr/9t5q54tirPz79kFIWg4dA== +node-releases@^1.1.52, node-releases@^1.1.61: + version "1.1.61" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.61.tgz#707b0fca9ce4e11783612ba4a2fcba09047af16e" + integrity sha512-DD5vebQLg8jLCOzwupn954fbIiZht05DAZs0k2u8NStSe6h9XdsuIQL8hSRKYiU8WUQRznmSDrKGbv3ObOmC7g== node-sass@^4.14.0: version "4.14.1" @@ -7614,7 +7667,7 @@ object-hash@^2.0.1: resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.0.3.tgz#d12db044e03cd2ca3d77c0570d87225b02e1e6ea" integrity sha512-JPKn0GMu+Fa3zt3Bmr66JhokJU5BaNBIh4ZeTlaCBzrBsOeXzwcKKAK1tbLiPKgvwmPXsDvvLHoWh5Bm7ofIYg== -object-inspect@^1.7.0: +object-inspect@^1.7.0, object-inspect@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0" integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA== @@ -7627,7 +7680,7 @@ object-is@^1.0.1: define-properties "^1.1.3" es-abstract "^1.17.5" -object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: +object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== @@ -7645,14 +7698,14 @@ object-visit@^1.0.0: isobject "^3.0.0" object.assign@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" - integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== + version "4.1.1" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.1.tgz#303867a666cdd41936ecdedfb1f8f3e32a478cdd" + integrity sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA== dependencies: - define-properties "^1.1.2" - function-bind "^1.1.1" - has-symbols "^1.0.0" - object-keys "^1.0.11" + define-properties "^1.1.3" + es-abstract "^1.18.0-next.0" + has-symbols "^1.0.1" + object-keys "^1.1.1" object.entries@^1.1.0, object.entries@^1.1.1: version "1.1.2" @@ -7730,9 +7783,9 @@ onetime@^5.1.0: mimic-fn "^2.1.0" open@^7.0.2: - version "7.1.0" - resolved "https://registry.yarnpkg.com/open/-/open-7.1.0.tgz#68865f7d3cb238520fa1225a63cf28bcf8368a1c" - integrity sha512-lLPI5KgOwEYCDKXf4np7y1PBEkj7HYIyP2DY8mVDRnx0VIIu6bNrRB0R66TuO7Mack6EnTNLm4uvcl1UoklTpA== + version "7.2.1" + resolved "https://registry.yarnpkg.com/open/-/open-7.2.1.tgz#07b0ade11a43f2a8ce718480bdf3d7563a095195" + integrity sha512-xbYCJib4spUdmcs0g/2mK1nKo/jO2T7INClWd/beL7PFkXRWgr8B23ssDHX/USPn2M2IjDR5UdpYs6I67SnTSA== dependencies: is-docker "^2.0.0" is-wsl "^2.1.1" @@ -7950,13 +8003,13 @@ parse-json@^4.0.0: json-parse-better-errors "^1.0.1" parse-json@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.0.1.tgz#7cfe35c1ccd641bce3981467e6c2ece61b3b3878" - integrity sha512-ztoZ4/DYeXQq4E21v169sC8qWINGpcosGv9XhTDvg9/hWvx/zrFkc9BiWxR58OJLHGk28j5BL0SDLeV2WmFZlQ== + version "5.1.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.1.0.tgz#f96088cdf24a8faa9aea9a009f2d9d942c999646" + integrity sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ== dependencies: "@babel/code-frame" "^7.0.0" error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" + json-parse-even-better-errors "^2.3.0" lines-and-columns "^1.1.6" parse5@4.0.0: @@ -8211,9 +8264,9 @@ postcss-browser-comments@^3.0.0: postcss "^7" postcss-calc@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.3.tgz#d65cca92a3c52bf27ad37a5f732e0587b74f1623" - integrity sha512-IB/EAEmZhIMEIhG7Ov4x+l47UaXOS1n2f4FBUk/aKllQhtSCxWhTzn0nJgkqN7fo/jcWySvWTSB6Syk9L+31bA== + version "7.0.4" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.4.tgz#5e177ddb417341e6d4a193c5d9fd8ada79094f8b" + integrity sha512-0I79VRAd1UTkaHzY9w83P39YGO/M3bG7/tNLrHGEunBolfoGM0hSjrGvjoeaj0JE/zIw5GsI2KZ0UwDJqv5hjw== dependencies: postcss "^7.0.27" postcss-selector-parser "^6.0.2" @@ -8867,9 +8920,9 @@ prepend-http@^1.0.0: integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= pretty-bytes@^5.1.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.3.0.tgz#f2849e27db79fb4d6cfe24764fc4134f165989f2" - integrity sha512-hjGrh+P926p4R4WbaB6OckyRtO0F0/lQBiT+0gnxjV+5kjPBrfVBFCsCLbMqVQeydvIoouYTCmmEURiH3R1Bdg== + version "5.4.1" + resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.4.1.tgz#cd89f79bbcef21e3d21eb0da68ffe93f803e884b" + integrity sha512-s1Iam6Gwz3JI5Hweaz4GoCD1WUNUIyzePFy5+Js2hjwGVt2Z79wNN+ZKOZ2vB6C+Xs6njyB84Z1IthQg8d9LxA== pretty-error@^2.1.1: version "2.1.1" @@ -8889,7 +8942,7 @@ pretty-format@^24.0.0, pretty-format@^24.3.0, pretty-format@^24.9.0: ansi-styles "^3.2.0" react-is "^16.8.4" -pretty-format@^25.1.0, pretty-format@^25.5.0: +pretty-format@^25.1.0: version "25.5.0" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-25.5.0.tgz#7873c1d774f682c34b8d48b6743a2bf2ac55791a" integrity sha512-kbo/kq2LQ/A/is0PQwsEHM7Ca6//bGPPvU6UnsdDRSKTWxT/ru/xb88v4BJf6a69H+uTytOEsTusT9ksd/1iWQ== @@ -8899,6 +8952,16 @@ pretty-format@^25.1.0, pretty-format@^25.5.0: ansi-styles "^4.0.0" react-is "^16.12.0" +pretty-format@^26.4.2: + version "26.4.2" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.4.2.tgz#d081d032b398e801e2012af2df1214ef75a81237" + integrity sha512-zK6Gd8zDsEiVydOCGLkoBoZuqv8VTiHyAbKznXe/gaph/DAeZOmit9yMfgIz5adIgAMMs5XfoYSwAX3jcCO1tA== + dependencies: + "@jest/types" "^26.3.0" + ansi-regex "^5.0.0" + ansi-styles "^4.0.0" + react-is "^16.12.0" + process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" @@ -9774,9 +9837,9 @@ run-queue@^1.0.0, run-queue@^1.0.3: aproba "^1.1.1" rxjs@^6.5.3, rxjs@^6.6.0: - version "6.6.2" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.2.tgz#8096a7ac03f2cc4fe5860ef6e572810d9e01c0d2" - integrity sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg== + version "6.6.3" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.3.tgz#8ca84635c4daa900c0d3967a6ee7ac60271ee552" + integrity sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ== dependencies: tslib "^1.9.0" @@ -9873,13 +9936,13 @@ schema-utils@^1.0.0: ajv-keywords "^3.1.0" schema-utils@^2.5.0, schema-utils@^2.6.0, schema-utils@^2.6.1, schema-utils@^2.6.4, schema-utils@^2.6.5: - version "2.7.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.0.tgz#17151f76d8eae67fbbf77960c33c676ad9f4efc7" - integrity sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A== + version "2.7.1" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" + integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== dependencies: - "@types/json-schema" "^7.0.4" - ajv "^6.12.2" - ajv-keywords "^3.4.1" + "@types/json-schema" "^7.0.5" + ajv "^6.12.4" + ajv-keywords "^3.5.2" scss-tokenizer@^0.2.3: version "0.2.3" @@ -10070,12 +10133,12 @@ shellwords@^0.1.1: integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== side-channel@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.2.tgz#df5d1abadb4e4bf4af1cd8852bf132d2f7876947" - integrity sha512-7rL9YlPHg7Ancea1S96Pa8/QWb4BtXL/TZvS6B8XFetGBeuhAsfmUspK6DokBeZ64+Kj9TCNRD/30pVz1BvQNA== + version "1.0.3" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.3.tgz#cdc46b057550bbab63706210838df5d4c19519c3" + integrity sha512-A6+ByhlLkksFoUepsGxfj5x1gTSrs+OydsRptUxeNCabQpCFUvcwIczgOigI8vhY/OJCnPnyE9rGiwgvr9cS1g== dependencies: - es-abstract "^1.17.0-next.1" - object-inspect "^1.7.0" + es-abstract "^1.18.0-next.0" + object-inspect "^1.8.0" signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.3" @@ -10595,9 +10658,9 @@ supports-color@^6.1.0: has-flag "^3.0.0" supports-color@^7.0.0, supports-color@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" - integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== dependencies: has-flag "^4.0.0" @@ -10909,9 +10972,9 @@ type@^1.0.1: integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== type@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/type/-/type-2.0.0.tgz#5f16ff6ef2eb44f260494dae271033b29c09a9c3" - integrity sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow== + version "2.1.0" + resolved "https://registry.yarnpkg.com/type/-/type-2.1.0.tgz#9bdc22c648cf8cf86dd23d32336a41cfb6475e3f" + integrity sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA== typed.js@^2.0.11: version "2.0.11" @@ -11019,9 +11082,9 @@ upath@^1.1.1: integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== uri-js@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" - integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== + version "4.4.0" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.0.tgz#aa714261de793e8a82347a7bcc9ce74e86f28602" + integrity sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g== dependencies: punycode "^2.1.0" @@ -11346,9 +11409,9 @@ whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3, whatwg-encoding@^1.0.5: iconv-lite "0.4.24" whatwg-fetch@^3.0.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.4.0.tgz#e11de14f4878f773fbebcde8871b2c0699af8b30" - integrity sha512-rsum2ulz2iuZH08mJkT0Yi6JnKhwdw4oeyMjokgxd+mmqYSd9cPpOQf01TIWgjxG/U4+QR+AwKq6lSbXVxkyoQ== + version "3.4.1" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.4.1.tgz#e5f871572d6879663fa5674c8f833f15a8425ab3" + integrity sha512-sofZVzE1wKwO+EYPbWfiwzaKovWiZXf4coEzjGP9b2GBVgQRLQUZ2QcuPpQExGDAW5GItpEm6Tl4OU5mywnAoQ== whatwg-mimetype@^2.1.0, whatwg-mimetype@^2.2.0, whatwg-mimetype@^2.3.0: version "2.3.0" -- cgit v1.2.3-70-g09d2 From 81e22267dfddca85e9e515ce7683efa9c8541ac8 Mon Sep 17 00:00:00 2001 From: therealbobo Date: Mon, 14 Sep 2020 18:49:09 +0200 Subject: initial upload support --- frontend/src/views/App.js | 6 +++ frontend/src/views/Header.js | 2 +- frontend/src/views/Upload.js | 106 +++++++++++++++++++++++++++++++++++++++++ frontend/src/views/Upload.scss | 21 ++++++++ 4 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 frontend/src/views/Upload.js create mode 100644 frontend/src/views/Upload.scss diff --git a/frontend/src/views/App.js b/frontend/src/views/App.js index 5a2d913..ebead2f 100644 --- a/frontend/src/views/App.js +++ b/frontend/src/views/App.js @@ -7,6 +7,7 @@ import Services from "./Services"; import Filters from "./Filters"; import Rules from "./Rules"; import Config from "./Config"; +import Upload from "./Upload"; class App extends Component { @@ -17,6 +18,7 @@ class App extends Component { filterWindowOpen: false, rulesWindowOpen: false, configWindowOpen: false, + uploadWindowOpen: false, configDone: false }; @@ -47,6 +49,9 @@ class App extends Component { modal = this.setState({configWindowOpen: false})} onDone={() => this.setState({configDone: true})}/>; } + if (this.state.uploadWindowOpen) { + modal = this.setState({uploadWindowOpen: false}) }/>; + } return (
@@ -55,6 +60,7 @@ class App extends Component { onOpenFilters={() => this.setState({filterWindowOpen: true})} onOpenRules={() => this.setState({rulesWindowOpen: true})} onOpenConfig={() => this.setState({configWindowOpen: true})} + onOpenUpload={() => this.setState({uploadWindowOpen: true})} onConfigDone={this.state.configDone} /> diff --git a/frontend/src/views/Header.js b/frontend/src/views/Header.js index 3f95bcd..0af7abf 100644 --- a/frontend/src/views/Header.js +++ b/frontend/src/views/Header.js @@ -70,7 +70,7 @@ class Header extends Component {
- + + + + + ); + } +} + +export default Upload; diff --git a/frontend/src/views/Upload.scss b/frontend/src/views/Upload.scss new file mode 100644 index 0000000..e327b8c --- /dev/null +++ b/frontend/src/views/Upload.scss @@ -0,0 +1,21 @@ +@import '../colors.scss'; + +.curl-output { + width: 100%; + font-size: 13px; +} + +#pcap-upload{ + align: center; + width: 100%; +} + +.btn-color { + border: 3px solid #fff; +} + +.dialog-footer { + .btn { + width: 80px; + } +} -- cgit v1.2.3-70-g09d2 From 54f55f9ad4af4d50f0fca371b9a14308b1d80c6b Mon Sep 17 00:00:00 2001 From: therealbobo Date: Thu, 17 Sep 2020 14:17:11 +0200 Subject: intial local processing support --- frontend/src/views/Upload.js | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/frontend/src/views/Upload.js b/frontend/src/views/Upload.js index 522afe8..d3f6bf3 100644 --- a/frontend/src/views/Upload.js +++ b/frontend/src/views/Upload.js @@ -1,6 +1,6 @@ import React, {Component} from 'react'; import './Upload.scss'; -import {Button, ButtonGroup, Col, Container, Form, FormControl, InputGroup, Modal, Row, Table} from "react-bootstrap"; +import {Button, ButtonGroup, Col, Container, Form, FormFile, InputGroup, Modal, Row, Table} from "react-bootstrap"; import bsCustomFileInput from 'bs-custom-file-input' import {createCurlCommand} from '../utils'; @@ -25,6 +25,30 @@ class Upload extends Component { bsCustomFileInput.init() } + onFileProcess = () => { + const formData = new FormData(); + formData.append( + "file", + this.state.selectedFile.name + ); + fetch('/api/pcap/file', { + method: 'POST', + body: formData + }) + .then(response => { + if (response.status === 202 ){ + this.props.onHide(); + } else { + response.json().then(data => { + this.setState( + {errors : data.error.toString()} + ); + }); + } + } + ); + } + onFileUpload = () => { const formData = new FormData(); formData.append( @@ -80,6 +104,17 @@ class Upload extends Component { custom /> +
+ + + +
@@ -95,6 +130,7 @@ class Upload extends Component { + -- cgit v1.2.3-70-g09d2 From 65f9bb547a24dd851d366f22950cb4301f3e8ae4 Mon Sep 17 00:00:00 2001 From: therealbobo Date: Thu, 17 Sep 2020 18:36:47 +0200 Subject: full support to upload/load --- frontend/src/views/Upload.js | 112 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 94 insertions(+), 18 deletions(-) diff --git a/frontend/src/views/Upload.js b/frontend/src/views/Upload.js index d3f6bf3..29d514d 100644 --- a/frontend/src/views/Upload.js +++ b/frontend/src/views/Upload.js @@ -1,6 +1,6 @@ import React, {Component} from 'react'; import './Upload.scss'; -import {Button, ButtonGroup, Col, Container, Form, FormFile, InputGroup, Modal, Row, Table} from "react-bootstrap"; +import {Button, ButtonGroup, ToggleButton, Col, Container, Form, FormFile, InputGroup, Modal, Row, Table} from "react-bootstrap"; import bsCustomFileInput from 'bs-custom-file-input' import {createCurlCommand} from '../utils'; @@ -11,11 +11,34 @@ class Upload extends Component { this.state = { selectedFile: null, + removeOriginal: false, + flushAll: false, errors: "" }; + this.flushAllChanged = this.flushAllChanged.bind(this); + this.removeOriginalChanged = this.removeOriginalChanged.bind(this); + + + } + + flushAllChanged() { + this.setState({flushAll: !this.value}); + this.checked = !this.checked; + this.value = !this.value; + } + + removeOriginalChanged() { + this.setState({removeOriginal: !this.value}); + this.checked = !this.checked; + this.value = !this.value; } + onLocalFileChange = event => { + this.setState({ selectedFile: event.target.value }); + + }; + onFileChange = event => { this.setState({ selectedFile: event.target.files[0] }); @@ -26,14 +49,14 @@ class Upload extends Component { } onFileProcess = () => { - const formData = new FormData(); - formData.append( - "file", - this.state.selectedFile.name - ); + const data = { + "file": this.state.selectedFile, + "flush_all": this.state.flushAll, + "delete_original_file": this.state.removeOriginal}; + fetch('/api/pcap/file', { method: 'POST', - body: formData + body: JSON.stringify(data) }) .then(response => { if (response.status === 202 ){ @@ -89,12 +112,31 @@ class Upload extends Component { > - /usr/bin/upload + /usr/bin/load_pcap + + --local + + + --upload + + + + + + + + -
+
- + + + this.removeOriginalChanged()} + > + --remove-original-file + + + + + + + + + + this.flushAllChanged()} + > + --flush-all + + + + + + + + +
+ + + +
+ +

@@ -130,8 +208,6 @@ class Upload extends Component {
- - -- cgit v1.2.3-70-g09d2 From 8d07bfe5f17534b7301a064aeaf8ed8071f10a40 Mon Sep 17 00:00:00 2001 From: Emiliano Ciavatta Date: Wed, 23 Sep 2020 20:19:09 +0200 Subject: Frontend refactor: checkpoint --- .travis.yml | 1 - frontend/src/backend.js | 36 ++++++ frontend/src/colors.scss | 32 +++++- frontend/src/components/Connection.js | 27 ++--- frontend/src/components/ConnectionContent.js | 6 +- frontend/src/components/fields/StringField.js | 31 ++++++ frontend/src/components/fields/StringField.scss | 66 +++++++++++ .../src/components/filters/FiltersDefinitions.js | 33 ++++-- .../components/filters/RulesConnectionsFilter.js | 6 +- frontend/src/components/panels/PcapPane.js | 121 +++++++++++++++++++++ frontend/src/components/panels/PcapPane.scss | 55 ++++++++++ frontend/src/index.scss | 58 +++++++++- frontend/src/utils.js | 18 +++ frontend/src/views/Config.js | 8 +- frontend/src/views/Connections.js | 23 ++-- frontend/src/views/Footer.js | 4 +- frontend/src/views/Header.js | 12 +- frontend/src/views/Header.scss | 4 + frontend/src/views/MainPane.js | 8 +- frontend/src/views/Rules.js | 4 +- frontend/src/views/Services.js | 33 ++---- 21 files changed, 489 insertions(+), 97 deletions(-) create mode 100644 frontend/src/backend.js create mode 100644 frontend/src/components/fields/StringField.js create mode 100644 frontend/src/components/fields/StringField.scss create mode 100644 frontend/src/components/panels/PcapPane.js create mode 100644 frontend/src/components/panels/PcapPane.scss diff --git a/.travis.yml b/.travis.yml index 1d66f6e..b59b12f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,6 @@ services: - docker before_script: - - docker pull eciavatta/caronte-env - docker pull mongo:4 - docker-compose -f docker-compose.testing.yml up -d --build diff --git a/frontend/src/backend.js b/frontend/src/backend.js new file mode 100644 index 0000000..35ae6e3 --- /dev/null +++ b/frontend/src/backend.js @@ -0,0 +1,36 @@ + +async function request(method, url, data) { + const options = { + method: method, + mode: "cors", + cache: "no-cache", + credentials: "same-origin", + headers: { + "Content-Type": "application/json" + }, + redirect: "follow", + referrerPolicy: "no-referrer", + }; + if (data != null) { + options.body = JSON.stringify(data); + } + const result = await fetch(url, options); + return result.json(); +} + +const backend = { + get: (url = "") => { + return request("GET", url, null); + }, + post: (url = "", data = null) => { + return request("POST", url, data); + }, + put: (url = "", data = null) => { + return request("PUT", url, data); + }, + delete: (url = "", data = null) => { + return request("DELETE", url, data); + } +}; + +export default backend; diff --git a/frontend/src/colors.scss b/frontend/src/colors.scss index 064f9f5..d982f03 100644 --- a/frontend/src/colors.scss +++ b/frontend/src/colors.scss @@ -10,10 +10,30 @@ $color-secondary-2: #df3030; $color-secondary-3: #ff9d9d; $color-secondary-4: #ffdfdf; -$color-blue: #247085; -$color-blue-light: #a5b8be; -$color-blue-dark: #013b4c; +$color-red: #E53935; +$color-red-light: #FFEBEE; +$color-red-dark: #B71C1C; -$color-green: #25965d; -$color-green-light: #cde4d8; -$color-green-dark: #004321; +$color-pink: #D81B60; +$color-pink-light: #FCE4EC; +$color-pink-dark: #880E4F; + +$color-purple: #8E24AA; +$color-purple-light: #F3E5F5; +$color-purple-dark: #4A148C; + +$color-deep-purple: #5E35B1; +$color-deep-purple-light: #EDE7F6; +$color-deep-purple-dark: #311B92; + +$color-indigo: #3949AB; +$color-indigo-light: #E8EAF6; +$color-indigo-dark: #1A237E; + +$color-green: #43A047; +$color-green-light: #E8F5E9; +$color-green-dark: #1B5E20; + +$color-blue: #1E88E5; +$color-blue-light: #E3F2FD; +$color-blue-dark: #0D47A1; diff --git a/frontend/src/components/Connection.js b/frontend/src/components/Connection.js index 93c6438..1149584 100644 --- a/frontend/src/components/Connection.js +++ b/frontend/src/components/Connection.js @@ -1,7 +1,8 @@ import React, {Component} from 'react'; import './Connection.scss'; -import axios from 'axios' import {Button, Form, OverlayTrigger, Popover} from "react-bootstrap"; +import backend from "../backend"; +import {formatSize} from "../utils"; class Connection extends Component { @@ -19,22 +20,18 @@ class Connection extends Component { 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}); - } + backend.post(`/api/connections/${this.props.data.id}/${enabled ? "hide" : "show"}`) + .then(_ => { + 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}); - } + backend.post(`/api/connections/${this.props.data.id}/${marked ? "unmark" : "mark"}`) + .then(_ => { + this.props.onMarked(!marked); + this.setState({update: true}); }); } if (name === "copy") { @@ -114,8 +111,8 @@ class Connection extends Component { {duration} - {conn.client_bytes} - {conn.server_bytes} + {formatSize(conn.client_bytes)} + {formatSize(conn.server_bytes)} {/*Hide this connection from the list)}>*/} diff --git a/frontend/src/components/ConnectionContent.js b/frontend/src/components/ConnectionContent.js index 20ec92b..0c00e8e 100644 --- a/frontend/src/components/ConnectionContent.js +++ b/frontend/src/components/ConnectionContent.js @@ -1,8 +1,8 @@ import React, {Component} from 'react'; import './ConnectionContent.scss'; import {Button, Dropdown, Row} from 'react-bootstrap'; -import axios from 'axios'; import MessageAction from "./MessageAction"; +import backend from "../backend"; const classNames = require('classnames'); @@ -27,9 +27,9 @@ class ConnectionContent extends Component { this.props.connection !== prevProps.connection || this.state.format !== prevState.format)) { this.setState({loading: true}); // TODO: limit workaround. - axios.get(`/api/streams/${this.props.connection.id}?format=${this.state.format}&limit=999999`).then(res => { + backend.get(`/api/streams/${this.props.connection.id}?format=${this.state.format}&limit=999999`).then(res => { this.setState({ - connectionContent: res.data, + connectionContent: res, loading: false }); }); diff --git a/frontend/src/components/fields/StringField.js b/frontend/src/components/fields/StringField.js new file mode 100644 index 0000000..09fe24d --- /dev/null +++ b/frontend/src/components/fields/StringField.js @@ -0,0 +1,31 @@ +import React, {Component} from 'react'; +import './StringField.scss'; + +const classNames = require('classnames'); + +class StringField extends Component { + + render() { + return ( +
+
+
+ {this.props.name}: +
+ +
+ + { this.props.active && +
+ this.props.onValueChanged("")}>del +
+ } +
+ ); + } +} + +export default StringField; diff --git a/frontend/src/components/fields/StringField.scss b/frontend/src/components/fields/StringField.scss new file mode 100644 index 0000000..7efac56 --- /dev/null +++ b/frontend/src/components/fields/StringField.scss @@ -0,0 +1,66 @@ +@import '../../colors.scss'; + +.field { + margin: 0 10px; + position: relative; + + .field-name-wrapper { + background-color: $color-primary-2; + padding: 3px 7px; + border-top-left-radius: 5px; + border-bottom-left-radius: 5px; + } + + .field-name { + font-size: 13px; + } + + .field-value { + font-size: 13px; + padding-left: 0; + border-radius: 5px; + + &:focus { + background-color: $color-primary-2; + } + } + + &.field-active { + .field-name-wrapper { + background-color: $color-primary-4; + color: $color-primary-3; + } + + .field-value { + background-color: $color-primary-4; + color: $color-primary-3; + } + } + + &.field-invalid { + .field-name-wrapper { + background-color: $color-secondary-2; + color: $color-primary-4; + } + + .field-value { + background-color: $color-secondary-2; + color: $color-primary-4; + } + } + + .field-delete { + position: absolute; + right: 10px; + top: 10px; + z-index: 10; + font-size: 11px; + letter-spacing: -0.5px; + color: $color-primary-2; + cursor: pointer; + + .field-delete-icon { + font-weight: 800; + } + } +} diff --git a/frontend/src/components/filters/FiltersDefinitions.js b/frontend/src/components/filters/FiltersDefinitions.js index a582d02..d36792e 100644 --- a/frontend/src/components/filters/FiltersDefinitions.js +++ b/frontend/src/components/filters/FiltersDefinitions.js @@ -21,49 +21,60 @@ export const filtersDefinitions = { service_port: , + validateFunc={validatePort} + key="service_port_filter" />, matched_rules: , client_address: , + validateFunc={validateIpAddress} + key="client_address_filter" />, client_port: , + validateFunc={validatePort} + key="client_port_filter" />, min_duration: , + validateFunc={validateMin(0)} + key="min_duration_filter" />, max_duration: , + replaceFunc={cleanNumber} + key="max_duration_filter" />, min_bytes: , + validateFunc={validateMin(0)} + key="min_bytes_filter" />, max_bytes: , + replaceFunc={cleanNumber} + key="max_bytes_filter" />, started_after: , + decodeFunc={timestampToTime} + key="started_after_filter" />, started_before: , + decodeFunc={timestampToTime} + key="started_before_filter" />, closed_after: , + decodeFunc={timestampToTime} + key="closed_after_filter" />, closed_before: , + decodeFunc={timestampToTime} + key="closed_before_filter" />, marked: , hidden: }; diff --git a/frontend/src/components/filters/RulesConnectionsFilter.js b/frontend/src/components/filters/RulesConnectionsFilter.js index 358085f..621b6d6 100644 --- a/frontend/src/components/filters/RulesConnectionsFilter.js +++ b/frontend/src/components/filters/RulesConnectionsFilter.js @@ -3,7 +3,7 @@ import {withRouter} from "react-router-dom"; import {Redirect} from "react-router"; import './RulesConnectionsFilter.scss'; import ReactTags from 'react-tag-autocomplete'; -import axios from 'axios'; +import backend from "../../backend"; const classNames = require('classnames'); @@ -24,8 +24,8 @@ class RulesConnectionsFilter extends Component { let params = new URLSearchParams(this.props.location.search); let activeRules = params.getAll("matched_rules") || []; - axios.get("/api/rules").then(res => { - let rules = res.data.flatMap(rule => rule.enabled ? [{id: rule.id, name: rule.name}] : []); + backend.get("/api/rules").then(res => { + let rules = res.flatMap(rule => rule.enabled ? [{id: rule.id, name: rule.name}] : []); activeRules = rules.filter(rule => activeRules.some(id => rule.id === id)); this.setState({rules, activeRules, mounted: true}); }); diff --git a/frontend/src/components/panels/PcapPane.js b/frontend/src/components/panels/PcapPane.js new file mode 100644 index 0000000..817c7b5 --- /dev/null +++ b/frontend/src/components/panels/PcapPane.js @@ -0,0 +1,121 @@ +import React, {Component} from 'react'; +import './PcapPane.scss'; +import Table from "react-bootstrap/Table"; +import backend from "../../backend"; +import {formatSize, timestampToTime2} from "../../utils"; +import {Container, Row, Col, Form} from "react-bootstrap"; +import StringField from "../fields/StringField"; + +class PcapPane extends Component { + + constructor(props) { + super(props); + + this.state = { + sessions: [], + }; + + this.loadSessions = this.loadSessions.bind(this); + } + + componentDidMount() { + this.loadSessions(); + } + + loadSessions() { + backend.get("/api/pcap/sessions").then(res => this.setState({sessions: res})); + } + + render() { + let sessions = this.state.sessions.map(s => + + {s["id"].substring(0, 8)} + {timestampToTime2(s["started_at"])} + {((new Date(s["completed_at"]) - new Date(s["started_at"])) / 1000).toFixed(3)}s + {formatSize(s["size"])} + {s["processed_packets"]} + {s["invalid_packets"]} + undefined + download + + ); + + return ( +
+
+
+ GET /api/pcap/sessions + 200 OK +
+ +
+ + + + + + + + + + + + + + + {sessions} + +
idstarted_atdurationsizeprocessed_packetsinvalid_packetspackets_per_serviceactions
+
+
+ +
+ + + +
+ POST /api/pcap/upload + +
+ +
+ + + +



+ + +
+ + + +
+ POST /api/pcap/file + +
+ +
+ +
+ +
+
+ + + + +
+ +
+ + ); + } +} + +export default PcapPane; diff --git a/frontend/src/components/panels/PcapPane.scss b/frontend/src/components/panels/PcapPane.scss new file mode 100644 index 0000000..3df87f5 --- /dev/null +++ b/frontend/src/components/panels/PcapPane.scss @@ -0,0 +1,55 @@ +@import '../../colors.scss'; + +.pane-container { + background-color: $color-primary-3; + padding: 10px 10px 0; + height: 100%; + + .section-header { + background-color: $color-primary-2; + padding: 5px 10px; + height: 31px; + + font-weight: 500; + font-size: 14px; + + .api-response { + float: right; + } + } + + .section-table { + margin-top: 10px; + + .table-row { + background-color: $color-primary-0; + border-top: 3px solid $color-primary-3; + border-bottom: 3px solid $color-primary-3; + } + + .table-cell-action { + font-size: 13px; + font-weight: 600; + } + } + + .section-content { + background-color: $color-primary-0; + padding: 10px; + } + + + + th { + background-color: $color-primary-2; + border-top: 3px solid $color-primary-3; + border-bottom: 3px solid $color-primary-3; + font-size: 13.5px; + position: sticky; + top: 10px; + padding: 5px; + } + + + +} \ No newline at end of file diff --git a/frontend/src/index.scss b/frontend/src/index.scss index 53ce4dd..358fd70 100644 --- a/frontend/src/index.scss +++ b/frontend/src/index.scss @@ -49,14 +49,62 @@ pre { } .btn-red { - color: $color-secondary-4; - background-color: $color-secondary-2; - border-bottom: 5px solid $color-secondary-1; + color: $color-red-light; + background-color: $color-red; + border-bottom: 5px solid $color-red-dark; &:hover, &:active { - color: $color-secondary-4; - background-color: $color-secondary-1; + color: $color-red-light; + background-color: $color-red-dark; + } +} + +.btn-pink { + color: $color-pink-light; + background-color: $color-pink; + border-bottom: 5px solid $color-pink-dark; + + &:hover, + &:active { + color: $color-pink-light; + background-color: $color-pink-dark; + } +} + +.btn-purple { + color: $color-purple-light; + background-color: $color-purple; + border-bottom: 5px solid $color-purple-dark; + + &:hover, + &:active { + color: $color-purple-light; + background-color: $color-purple-dark; + } +} + +.btn-deep-purple { + color: $color-deep-purple-light; + background-color: $color-deep-purple; + border-bottom: 5px solid $color-deep-purple-dark; + + &:hover, + &:active { + color: $color-deep-purple-light; + background-color: $color-deep-purple-dark; + } +} + +.btn-indigo { + color: $color-indigo-light; + background-color: $color-indigo; + border-bottom: 5px solid $color-indigo-dark; + + &:hover, + &:active { + color: $color-indigo-light; + background-color: $color-indigo-dark; } } diff --git a/frontend/src/utils.js b/frontend/src/utils.js index 7381f69..4991755 100644 --- a/frontend/src/utils.js +++ b/frontend/src/utils.js @@ -64,3 +64,21 @@ export function timestampToDateTime(timestamp) { let d = new Date(timestamp); return d.toLocaleDateString() + " " + d.toLocaleTimeString(); } + +export function timestampToTime2(timestamp) { + let d = new Date(timestamp); + let hours = d.getHours(); + let minutes = "0" + d.getMinutes(); + let seconds = "0" + d.getSeconds(); + return hours + ':' + minutes.substr(-2) + ':' + seconds.substr(-2); +} + +export function formatSize(size) { + if (size < 1000) { + return `${size}`; + } else if (size < 1000000) { + return `${(size / 1000).toFixed(1)}K`; + } else { + return `${(size / 1000000).toFixed(1)}M`; + } +} diff --git a/frontend/src/views/Config.js b/frontend/src/views/Config.js index f5766eb..a770378 100644 --- a/frontend/src/views/Config.js +++ b/frontend/src/views/Config.js @@ -1,10 +1,6 @@ -import { - validateIpAddress, -} from "../utils"; -import React, {Component, useState} from 'react'; +import React, {Component} from 'react'; import './Config.scss'; -import {Button, ButtonGroup, ToggleButton, Col, Container, Form, FormControl, InputGroup, Modal, Row, Table} from "react-bootstrap"; -import {createCurlCommand} from '../utils'; +import {Button, ButtonGroup, Col, Container, Form, Modal, Row, Table, ToggleButton} from "react-bootstrap"; class Config extends Component { diff --git a/frontend/src/views/Connections.js b/frontend/src/views/Connections.js index 62733d7..da8958b 100644 --- a/frontend/src/views/Connections.js +++ b/frontend/src/views/Connections.js @@ -1,10 +1,10 @@ import React, {Component} from 'react'; import './Connections.scss'; -import axios from 'axios'; import Connection from "../components/Connection"; import Table from 'react-bootstrap/Table'; import {Redirect} from 'react-router'; import {withRouter} from "react-router-dom"; +import backend from "../backend"; class Connections extends Component { @@ -75,15 +75,15 @@ class Connections extends Component { } this.setState({loading: true, prevParams: params}); - let res = await axios.get(`${url}?${urlParams}`); + let res = await backend.get(`${url}?${urlParams}`); let connections = this.state.connections; let firstConnection = this.state.firstConnection; let lastConnection = this.state.lastConnection; if (params !== undefined && params.from !== undefined) { - if (res.data.length > 0) { - connections = this.state.connections.concat(res.data); + if (res.length > 0) { + connections = this.state.connections.concat(res); lastConnection = connections[connections.length - 1]; if (connections.length > this.maxConnections) { connections = connections.slice(connections.length - this.maxConnections, @@ -92,8 +92,8 @@ class Connections extends Component { } } } else if (params !== undefined && params.to !== undefined) { - if (res.data.length > 0) { - connections = res.data.concat(this.state.connections); + if (res.length > 0) { + connections = res.concat(this.state.connections); firstConnection = connections[0]; if (connections.length > this.maxConnections) { connections = connections.slice(0, this.maxConnections); @@ -101,8 +101,8 @@ class Connections extends Component { } } } else { - if (res.data.length > 0) { - connections = res.data; + if (res.length > 0) { + connections = res; firstConnection = connections[0]; lastConnection = connections[connections.length - 1]; } else { @@ -115,8 +115,7 @@ class Connections extends Component { let flagRule = this.state.flagRule; let rules = this.state.rules; if (flagRule === null) { - let res = await axios.get("/api/rules"); - rules = res.data; + rules = await backend.get("/api/rules"); flagRule = rules.filter(rule => { return rule.name === "flag"; })[0]; @@ -125,7 +124,7 @@ class Connections extends Component { this.setState({ loading: false, connections: connections, - rules: res.data, + rules: res, flagRule: flagRule, firstConnection: firstConnection, lastConnection: lastConnection @@ -134,7 +133,7 @@ class Connections extends Component { render() { let redirect; - let queryString = this.state.queryString !== null ? this.state.queryString : "" + let queryString = this.state.queryString !== null ? this.state.queryString : ""; if (this.state.selected) { let format = this.props.match.params.format; format = format !== undefined ? "/" + format : ""; diff --git a/frontend/src/views/Footer.js b/frontend/src/views/Footer.js index b6ffd9d..0a3c5a3 100644 --- a/frontend/src/views/Footer.js +++ b/frontend/src/views/Footer.js @@ -8,11 +8,11 @@ class Footer extends Component { - ) + ); } } diff --git a/frontend/src/views/Header.js b/frontend/src/views/Header.js index 0af7abf..5860d80 100644 --- a/frontend/src/views/Header.js +++ b/frontend/src/views/Header.js @@ -69,12 +69,12 @@ class Header extends Component {
- - - - - + + + + +
diff --git a/frontend/src/views/Header.scss b/frontend/src/views/Header.scss index e84e758..e36b2d6 100644 --- a/frontend/src/views/Header.scss +++ b/frontend/src/views/Header.scss @@ -16,6 +16,10 @@ .header-buttons { margin: 5px 0; text-align: right; + + button { + margin-left: 10px; + } } .filters-bar-wrapper { diff --git a/frontend/src/views/MainPane.js b/frontend/src/views/MainPane.js index 69de725..3c0d795 100644 --- a/frontend/src/views/MainPane.js +++ b/frontend/src/views/MainPane.js @@ -3,7 +3,8 @@ import './MainPane.scss'; import Connections from "./Connections"; import ConnectionContent from "../components/ConnectionContent"; import {withRouter} from "react-router-dom"; -import axios from 'axios'; +import PcapPane from "../components/panels/PcapPane"; +import backend from "../backend"; class MainPane extends Component { @@ -17,9 +18,9 @@ class MainPane extends Component { componentDidMount() { if ('id' in this.props.match.params) { const id = this.props.match.params.id; - axios.get(`/api/connections/${id}`).then(res => { + backend.get(`/api/connections/${id}`).then(res => { if (res.status === 200) { - this.setState({selectedConnection: res.data}); + this.setState({selectedConnection: res}); } }); } @@ -34,6 +35,7 @@ class MainPane extends Component { this.setState({selectedConnection: c})} />
+ {/**/}
diff --git a/frontend/src/views/Rules.js b/frontend/src/views/Rules.js index 3424410..bbc3bb6 100644 --- a/frontend/src/views/Rules.js +++ b/frontend/src/views/Rules.js @@ -1,7 +1,7 @@ import React, {Component} from 'react'; import './Services.scss'; import {Button, ButtonGroup, Col, Container, Form, FormControl, InputGroup, Modal, Row, Table} from "react-bootstrap"; -import axios from "axios"; +import backend from "../backend"; class Rules extends Component { @@ -18,7 +18,7 @@ class Rules extends Component { } loadRules() { - axios.get("/api/rules").then(res => this.setState({rules: res.data})); + backend.get("/api/rules").then(res => this.setState({rules: res.data})); } render() { diff --git a/frontend/src/views/Services.js b/frontend/src/views/Services.js index 0de021f..22d61b3 100644 --- a/frontend/src/views/Services.js +++ b/frontend/src/views/Services.js @@ -1,8 +1,8 @@ import React, {Component} from 'react'; import './Services.scss'; import {Button, ButtonGroup, Col, Container, Form, FormControl, InputGroup, Modal, Row, Table} from "react-bootstrap"; -import axios from 'axios' import {createCurlCommand} from '../utils'; +import backend from "../backend"; class Services extends Component { @@ -64,31 +64,20 @@ class Services extends Component { saveService() { if (this.state.portValid && this.state.nameValid) { - const requestOptions = { - method: 'PUT', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - color: this.state.color, - name: this.state.name, - notes: this.state.notes, - port: this.state.port, - }) - }; - - - fetch('/api/services', requestOptions) - .then(function(response){ - console.log(response); - } - ); - - this.newService(); - this.loadServices(); + backend.put("/api/services", { + color: this.state.color, + name: this.state.name, + notes: this.state.notes, + port: this.state.port, + }).then(_ => { + this.newService(); + this.loadServices(); + }); } } loadServices() { - axios.get("/api/services").then(res => this.setState({services: res.data})); + backend.get("/api/services").then(res => this.setState({services: res})); } componentDidUpdate(prevProps, prevState, snapshot) { -- cgit v1.2.3-70-g09d2 From 04ee54be31931111bf89e50e4e54ac92b9a19d7a Mon Sep 17 00:00:00 2001 From: Emiliano Ciavatta Date: Wed, 23 Sep 2020 22:00:56 +0200 Subject: Add StringField --- frontend/src/components/fields/StringField.js | 53 ++++++++--- frontend/src/components/fields/StringField.scss | 121 +++++++++++++++++------- frontend/src/utils.js | 4 + 3 files changed, 131 insertions(+), 47 deletions(-) diff --git a/frontend/src/components/fields/StringField.js b/frontend/src/components/fields/StringField.js index 09fe24d..aa23fe8 100644 --- a/frontend/src/components/fields/StringField.js +++ b/frontend/src/components/fields/StringField.js @@ -1,26 +1,55 @@ import React, {Component} from 'react'; import './StringField.scss'; +import {randomClassName} from "../../utils"; const classNames = require('classnames'); class StringField extends Component { render() { + const id = `field-${this.props.name || "noname"}-${randomClassName()}`; + const active = this.props.active || false; + const invalid = this.props.invalid || false; + const small = this.props.small || false; + const inline = this.props.inline || false; + const name = this.props.name || null; + const value = this.props.value || ""; + const type = this.props.type || "text"; + const error = this.props.error || null; + const handler = (e) => { + if (this.props.onChange) { + if (e == null) { + this.props.onChange(""); + } else { + this.props.onChange(e.target.value); + } + } + }; + return ( -
-
-
- {this.props.name}: +
+
+ { name && +
+ +
+ } +
+
+ +
+ { value !== "" && +
+ handler(null)}>del +
+ }
-
- - { this.props.active && -
- this.props.onValueChanged("")}>del + {error && +
+ error: {error}
}
diff --git a/frontend/src/components/fields/StringField.scss b/frontend/src/components/fields/StringField.scss index 7efac56..674815f 100644 --- a/frontend/src/components/fields/StringField.scss +++ b/frontend/src/components/fields/StringField.scss @@ -1,66 +1,117 @@ @import '../../colors.scss'; .field { - margin: 0 10px; - position: relative; - - .field-name-wrapper { - background-color: $color-primary-2; - padding: 3px 7px; - border-top-left-radius: 5px; - border-bottom-left-radius: 5px; - } + font-size: 0.9em; .field-name { - font-size: 13px; + label { + margin: 0; + } } - .field-value { - font-size: 13px; - padding-left: 0; - border-radius: 5px; + .field-input { + position: relative; - &:focus { + .field-value input { background-color: $color-primary-2; + width: 100%; + border: none; + color: $color-primary-4; + border-radius: 5px; + padding: 7px 10px; + + &:focus { + background-color: $color-primary-1; + color: $color-primary-4; + box-shadow: none; + outline: none; + } + + &[readonly] { + background-color: $color-primary-2; + border: none; + color: $color-primary-4; + } + + &[readonly]:focus { + background-color: $color-primary-1; + color: $color-primary-4; + box-shadow: none; + } } } &.field-active { - .field-name-wrapper { - background-color: $color-primary-4; - color: $color-primary-3; + &.field-inline .field-name { + background-color: $color-primary-4 !important; + color: $color-primary-3 !important; } - .field-value { - background-color: $color-primary-4; - color: $color-primary-3; + .field-value input { + background-color: $color-primary-4 !important; + color: $color-primary-3 !important; } } &.field-invalid { - .field-name-wrapper { - background-color: $color-secondary-2; - color: $color-primary-4; + &.field-inline .field-name { + background-color: $color-secondary-2 !important; + color: $color-primary-4 !important; } - .field-value { - background-color: $color-secondary-2; - color: $color-primary-4; + .field-value input { + background-color: $color-secondary-2 !important; + color: $color-primary-4 !important; + } + } + + &.field-small { + font-size: 0.8em; + } + + &.field-inline .field-wrapper { + display: flex; + + .field-name { + background-color: $color-primary-2; + padding: 6px 7px; + border-top-left-radius: 5px; + border-bottom-left-radius: 5px; + } + + .field-input { + width: 100%; + + input { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + padding-left: 3px; + } + } + + &:focus-within .field-name { + background-color: $color-primary-1; } } - .field-delete { + .field-clear { position: absolute; - right: 10px; - top: 10px; + right: 8px; + top: 8px; z-index: 10; - font-size: 11px; + font-size: 0.9em; + font-weight: 600; letter-spacing: -0.5px; - color: $color-primary-2; cursor: pointer; + } - .field-delete-icon { - font-weight: 800; - } + &.field-active .field-clear { + color: $color-primary-2; + } + + .field-error { + padding: 5px 10px; + font-size: 0.9em; + color: $color-secondary-0; } } diff --git a/frontend/src/utils.js b/frontend/src/utils.js index 4991755..c81cdfc 100644 --- a/frontend/src/utils.js +++ b/frontend/src/utils.js @@ -82,3 +82,7 @@ export function formatSize(size) { return `${(size / 1000000).toFixed(1)}M`; } } + +export function randomClassName(size = 10) { + return Math.random().toString(36).substring(size); +} -- cgit v1.2.3-70-g09d2 From 05678b74d98247c957faa1ca3d0bafc5f68974d1 Mon Sep 17 00:00:00 2001 From: Emiliano Ciavatta Date: Wed, 23 Sep 2020 23:16:58 +0200 Subject: Add BooleanField --- frontend/src/components/fields/BooleanField.js | 37 +++++++++++ frontend/src/components/fields/BooleanField.scss | 34 ++++++++++ frontend/src/components/fields/StringField.js | 16 +++-- frontend/src/components/fields/StringField.scss | 2 +- .../components/filters/BooleanConnectionsFilter.js | 12 ++-- .../filters/BooleanConnectionsFilter.scss | 24 ------- .../src/components/filters/FiltersDefinitions.js | 34 ++++++---- .../components/filters/StringConnectionsFilter.js | 31 ++------- .../filters/StringConnectionsFilter.scss | 66 ------------------- frontend/src/components/panels/PcapPane.js | 4 +- frontend/src/index.scss | 27 +------- frontend/src/utils.js | 4 +- frontend/src/views/Header.js | 6 +- frontend/src/views/Header.scss | 8 ++- frontend/src/views/MainPane.js | 4 +- frontend/yarn.lock | 74 +++++++++++----------- 16 files changed, 168 insertions(+), 215 deletions(-) create mode 100644 frontend/src/components/fields/BooleanField.js create mode 100644 frontend/src/components/fields/BooleanField.scss delete mode 100644 frontend/src/components/filters/BooleanConnectionsFilter.scss delete mode 100644 frontend/src/components/filters/StringConnectionsFilter.scss diff --git a/frontend/src/components/fields/BooleanField.js b/frontend/src/components/fields/BooleanField.js new file mode 100644 index 0000000..06a6da7 --- /dev/null +++ b/frontend/src/components/fields/BooleanField.js @@ -0,0 +1,37 @@ +import React, {Component} from 'react'; +import './BooleanField.scss'; +import {randomClassName} from "../../utils"; + +const classNames = require('classnames'); + +class BooleanField extends Component { + + constructor(props) { + super(props); + + this.id = `field-${this.props.name || "noname"}-${randomClassName()}`; + } + + render() { + + const checked = this.props.checked || false; + const small = this.props.small || false; + const name = this.props.name || null; + const handler = () => { + if (this.props.onChange) { + this.props.onChange(!checked); + } + }; + + return ( +
+
+ + +
+
+ ); + } +} + +export default BooleanField; diff --git a/frontend/src/components/fields/BooleanField.scss b/frontend/src/components/fields/BooleanField.scss new file mode 100644 index 0000000..6ec25f7 --- /dev/null +++ b/frontend/src/components/fields/BooleanField.scss @@ -0,0 +1,34 @@ +@import '../../colors.scss'; + +.boolean-field { + font-size: 0.9em; + + .field-input { + border-radius: 5px; + width: fit-content; + background-color: $color-primary-2; + + input { + display: none; + } + + label { + margin: 0; + padding: 6px 15px; + cursor: pointer; + } + + &:hover { + background-color: $color-primary-1; + } + } + + &.field-checked .field-input { + background-color: $color-primary-4 !important; + color: $color-primary-3; + } + + &.field-small { + font-size: 0.8em; + } +} diff --git a/frontend/src/components/fields/StringField.js b/frontend/src/components/fields/StringField.js index aa23fe8..7781b2d 100644 --- a/frontend/src/components/fields/StringField.js +++ b/frontend/src/components/fields/StringField.js @@ -6,8 +6,14 @@ const classNames = require('classnames'); class StringField extends Component { + constructor(props) { + super(props); + + this.id = `field-${this.props.name || "noname"}-${randomClassName()}`; + } + render() { - const id = `field-${this.props.name || "noname"}-${randomClassName()}`; + const active = this.props.active || false; const invalid = this.props.invalid || false; const small = this.props.small || false; @@ -27,18 +33,18 @@ class StringField extends Component { }; return ( -
+
{ name &&
- +
}
+ aria-describedby={this.id} onChange={handler} value={value} />
{ value !== "" &&
diff --git a/frontend/src/components/fields/StringField.scss b/frontend/src/components/fields/StringField.scss index 674815f..2523c8d 100644 --- a/frontend/src/components/fields/StringField.scss +++ b/frontend/src/components/fields/StringField.scss @@ -1,6 +1,6 @@ @import '../../colors.scss'; -.field { +.string-field { font-size: 0.9em; .field-name { diff --git a/frontend/src/components/filters/BooleanConnectionsFilter.js b/frontend/src/components/filters/BooleanConnectionsFilter.js index 7dea7cf..490d185 100644 --- a/frontend/src/components/filters/BooleanConnectionsFilter.js +++ b/frontend/src/components/filters/BooleanConnectionsFilter.js @@ -1,9 +1,7 @@ import React, {Component} from 'react'; import {withRouter} from "react-router-dom"; import {Redirect} from "react-router"; -import './BooleanConnectionsFilter.scss'; - -const classNames = require('classnames'); +import BooleanField from "../fields/BooleanField"; class BooleanConnectionsFilter extends Component { @@ -57,11 +55,9 @@ class BooleanConnectionsFilter extends Component { } return ( -
-
- {this.props.filterName} -
- +
+ {redirect}
); diff --git a/frontend/src/components/filters/BooleanConnectionsFilter.scss b/frontend/src/components/filters/BooleanConnectionsFilter.scss deleted file mode 100644 index 941b967..0000000 --- a/frontend/src/components/filters/BooleanConnectionsFilter.scss +++ /dev/null @@ -1,24 +0,0 @@ -@import '../../colors'; - -.filter { - .filter-boolean { - padding: 0 10px; - background-color: $color-primary-2; - border-radius: 5px; - cursor: pointer; - height: 34px; - - span { - display: block; - font-size: 13px; - padding: 6px 5px; - } - } - - &.filter-active { - .filter-boolean { - background-color: $color-primary-4; - color: $color-primary-3; - } - } -} diff --git a/frontend/src/components/filters/FiltersDefinitions.js b/frontend/src/components/filters/FiltersDefinitions.js index d36792e..02ccb42 100644 --- a/frontend/src/components/filters/FiltersDefinitions.js +++ b/frontend/src/components/filters/FiltersDefinitions.js @@ -12,7 +12,6 @@ import React from "react"; import RulesConnectionsFilter from "./RulesConnectionsFilter"; import BooleanConnectionsFilter from "./BooleanConnectionsFilter"; - export const filtersNames = ["service_port", "matched_rules", "client_address", "client_port", "min_duration", "max_duration", "min_bytes", "max_bytes", "started_after", "started_before", "closed_after", "closed_before", "marked", "hidden"]; @@ -22,59 +21,70 @@ export const filtersDefinitions = { defaultFilterValue="all_ports" replaceFunc={cleanNumber} validateFunc={validatePort} - key="service_port_filter" />, + key="service_port_filter" + width={200} />, matched_rules: , client_address: , + key="client_address_filter" + width={320} />, client_port: , + key="client_port_filter" + width={200} />, min_duration: , + key="min_duration_filter" + width={200} />, max_duration: , + key="max_duration_filter" + width={200} />, min_bytes: , + key="min_bytes_filter" + width={200} />, max_bytes: , + key="max_bytes_filter" + width={200} />, started_after: , + key="started_after_filter" + width={200} />, started_before: , + key="started_before_filter" + width={200} />, closed_after: , + key="closed_after_filter" + width={200} />, closed_before: , + key="closed_before_filter" + width={200} />, marked: , hidden: }; diff --git a/frontend/src/components/filters/StringConnectionsFilter.js b/frontend/src/components/filters/StringConnectionsFilter.js index 490a569..0d7f063 100644 --- a/frontend/src/components/filters/StringConnectionsFilter.js +++ b/frontend/src/components/filters/StringConnectionsFilter.js @@ -1,9 +1,7 @@ import React, {Component} from 'react'; import {withRouter} from "react-router-dom"; import {Redirect} from "react-router"; -import './StringConnectionsFilter.scss'; - -const classNames = require('classnames'); +import StringField from "../fields/StringField"; class StringConnectionsFilter extends Component { @@ -62,8 +60,7 @@ class StringConnectionsFilter extends Component { (typeof this.props.validateFunc === "function" && this.props.validateFunc(value)); } - filterChanged(event) { - let fieldValue = event.target.value; + filterChanged(fieldValue) { if (this.state.timeoutHandle !== null) { clearTimeout(this.state.timeoutHandle); } @@ -116,26 +113,10 @@ class StringConnectionsFilter extends Component { let active = this.state.filterValue !== null; return ( -
-
-
- {this.props.filterName}: -
- -
- - { active && -
- { - this.needRedirect = true; - this.setState({fieldValue: "", filterValue: null}); - }}>del -
- } - +
+ {redirect}
); diff --git a/frontend/src/components/filters/StringConnectionsFilter.scss b/frontend/src/components/filters/StringConnectionsFilter.scss deleted file mode 100644 index 1476616..0000000 --- a/frontend/src/components/filters/StringConnectionsFilter.scss +++ /dev/null @@ -1,66 +0,0 @@ -@import '../../colors'; - -.filter { - margin: 0 10px; - position: relative; - - .filter-name-wrapper { - background-color: $color-primary-2; - padding: 3px 7px; - border-top-left-radius: 5px; - border-bottom-left-radius: 5px; - } - - .filter-name { - font-size: 13px; - } - - .filter-value { - font-size: 13px; - padding-left: 0; - border-radius: 5px; - - &:focus { - background-color: $color-primary-2; - } - } - - &.filter-active { - .filter-name-wrapper { - background-color: $color-primary-4; - color: $color-primary-3; - } - - .filter-value { - background-color: $color-primary-4; - color: $color-primary-3; - } - } - - &.filter-invalid { - .filter-name-wrapper { - background-color: $color-secondary-2; - color: $color-primary-4; - } - - .filter-value { - background-color: $color-secondary-2; - color: $color-primary-4; - } - } - - .filter-delete { - position: absolute; - right: 10px; - top: 10px; - z-index: 10; - font-size: 11px; - letter-spacing: -0.5px; - color: $color-primary-2; - cursor: pointer; - - .filter-delete-icon { - font-weight: 800; - } - } -} diff --git a/frontend/src/components/panels/PcapPane.js b/frontend/src/components/panels/PcapPane.js index 817c7b5..9f3bc19 100644 --- a/frontend/src/components/panels/PcapPane.js +++ b/frontend/src/components/panels/PcapPane.js @@ -5,6 +5,7 @@ import backend from "../../backend"; import {formatSize, timestampToTime2} from "../../utils"; import {Container, Row, Col, Form} from "react-bootstrap"; import StringField from "../fields/StringField"; +import BooleanField from "../fields/BooleanField"; class PcapPane extends Component { @@ -13,6 +14,7 @@ class PcapPane extends Component { this.state = { sessions: [], + test: false }; this.loadSessions = this.loadSessions.bind(this); @@ -86,7 +88,7 @@ class PcapPane extends Component {



- + this.setState({test: v})} />
diff --git a/frontend/src/index.scss b/frontend/src/index.scss index 358fd70..5d1bbfa 100644 --- a/frontend/src/index.scss +++ b/frontend/src/index.scss @@ -13,6 +13,7 @@ body { color: $color-primary-4; height: 100%; max-height: 100%; + font-size: 100%; } pre { @@ -182,32 +183,6 @@ textarea.form-control { resize: none; } -input.form-control, -textarea.form-control { - background-color: $color-primary-2; - border: none; - color: $color-primary-4; - font-family: 'Fira Code', monospace; - - &:focus { - background-color: $color-primary-1; - color: $color-primary-4; - box-shadow: none; - } - - &[readonly] { - background-color: $color-primary-2; - border: none; - color: $color-primary-4; - } - - &[readonly]:focus { - background-color: $color-primary-1; - color: $color-primary-4; - box-shadow: none; - } -} - .table { color: $color-primary-4; } diff --git a/frontend/src/utils.js b/frontend/src/utils.js index c81cdfc..46667d6 100644 --- a/frontend/src/utils.js +++ b/frontend/src/utils.js @@ -83,6 +83,6 @@ export function formatSize(size) { } } -export function randomClassName(size = 10) { - return Math.random().toString(36).substring(size); +export function randomClassName() { + return Math.random().toString(36).slice(2) } diff --git a/frontend/src/views/Header.js b/frontend/src/views/Header.js index 5860d80..deb3ab7 100644 --- a/frontend/src/views/Header.js +++ b/frontend/src/views/Header.js @@ -60,10 +60,8 @@ class Header extends Component {
-
-
- {quickFilters} -
+
+ {quickFilters}
diff --git a/frontend/src/views/Header.scss b/frontend/src/views/Header.scss index e36b2d6..f3bfec1 100644 --- a/frontend/src/views/Header.scss +++ b/frontend/src/views/Header.scss @@ -22,8 +22,12 @@ } } - .filters-bar-wrapper { - height: 50px; + .filters-bar { padding: 8px 0; + + .filter { + display: inline-block; + margin-right: 10px; + } } } diff --git a/frontend/src/views/MainPane.js b/frontend/src/views/MainPane.js index 3c0d795..88af4a7 100644 --- a/frontend/src/views/MainPane.js +++ b/frontend/src/views/MainPane.js @@ -35,8 +35,8 @@ class MainPane extends Component { this.setState({selectedConnection: c})} />
- {/**/} - + + {/**/}
diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 39d346b..c5f59cb 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -1691,9 +1691,9 @@ integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== "@types/node@*": - version "14.10.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.10.2.tgz#9b47a2c8e4dabd4db73b57e750b24af689600514" - integrity sha512-IzMhbDYCpv26pC2wboJ4MMOa9GKtjplXfcAqrMeNJpUUwpM/2ATt2w1JPUXwS6spu856TvKZL2AOmeU2rAxskw== + version "14.11.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.11.1.tgz#56af902ad157e763f9ba63d671c39cda3193c835" + integrity sha512-oTQgnd0hblfLsJ6BvJzzSL+Inogp3lq9fGgqRkMB/ziKMgEUaFl801OncOzUmalfzt14N0oPHMK47ipl+wbTIw== "@types/parse-json@^4.0.0": version "4.0.0" @@ -2792,20 +2792,19 @@ browserslist@4.10.0: pkg-up "^3.1.0" browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.6.2, browserslist@^4.6.4, browserslist@^4.8.5, browserslist@^4.9.1: - version "4.14.2" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.2.tgz#1b3cec458a1ba87588cc5e9be62f19b6d48813ce" - integrity sha512-HI4lPveGKUR0x2StIz+2FXfDk9SfVMrxn6PLh1JeGUwcuoDkdKZebWiyLRJ68iIPDpMI4JLVDf7S7XzslgWOhw== + version "4.14.3" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.3.tgz#381f9e7f13794b2eb17e1761b4f118e8ae665a53" + integrity sha512-GcZPC5+YqyPO4SFnz48/B0YaCwS47Q9iPChRGi6t7HhflKBcINzFrJvRfC+jp30sRMKxF+d4EHGs27Z0XP1NaQ== dependencies: - caniuse-lite "^1.0.30001125" - electron-to-chromium "^1.3.564" - escalade "^3.0.2" + caniuse-lite "^1.0.30001131" + electron-to-chromium "^1.3.570" + escalade "^3.1.0" node-releases "^1.1.61" bs-custom-file-input@^1.3.4: version "1.3.4" resolved "https://registry.yarnpkg.com/bs-custom-file-input/-/bs-custom-file-input-1.3.4.tgz#c275cb8d4f1c02ba026324292509fa9a747dbda8" integrity sha512-NBsQzTnef3OW1MvdKBbMHAYHssCd613MSeJV7z2McXznWtVMnJCy7Ckyc+PwxV6Pk16cu6YBcYWh/ZE0XWNKCA== ->>>>>>> 98355cdf838d8c18e9a28176ae7a847770545395 bser@2.1.1: version "2.1.1" @@ -2983,10 +2982,10 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001035, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001125: - version "1.0.30001131" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001131.tgz#afad8a28fc2b7a0d3ae9407e71085a0ead905d54" - integrity sha512-4QYi6Mal4MMfQMSqGIRPGbKIbZygeN83QsWq1ixpUwvtfgAZot5BrCKzGygvZaV+CnELdTwD0S4cqUNozq7/Cw== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001035, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001131: + version "1.0.30001133" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001133.tgz#ec564c5495311299eb05245e252d589a84acd95e" + integrity sha512-s3XAUFaC/ntDb1O3lcw9K8MPeOW7KO3z9+GzAoBxfz1B0VdacXPMKgFUtG4KIsgmnbexmi013s9miVu4h+qMHw== capture-exit@^2.0.0: version "2.0.0" @@ -3828,11 +3827,11 @@ debug@^3.1.1, debug@^3.2.5: ms "^2.1.1" debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" - integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== + version "4.2.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1" + integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== dependencies: - ms "^2.1.1" + ms "2.1.2" decamelize@^1.1.2, decamelize@^1.2.0: version "1.2.0" @@ -4152,7 +4151,7 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= -electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.564: +electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.570: version "1.3.570" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.570.tgz#3f5141cc39b4e3892a276b4889980dabf1d29c7f" integrity sha512-Y6OCoVQgFQBP5py6A/06+yWxUZHDlNr/gNDGatjH8AZqXl8X0tE4LfjLJsXGz/JmWJz8a6K7bR1k+QzZ+k//fg== @@ -4305,7 +4304,7 @@ es6-symbol@^3.1.1, es6-symbol@~3.1.3: d "^1.0.1" ext "^1.1.2" -escalade@^3.0.2: +escalade@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.0.tgz#e8e2d7c7a8b76f6ee64c2181d6b8151441602d4e" integrity sha512-mAk+hPSO8fLDkhV7V0dXazH5pDc6MrjBTPyD3VeKzxnVFjH1MIxbCdqGZB9O8+EwWakZs3ZCbDS4IpRt79V1ig== @@ -7377,7 +7376,7 @@ ms@2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== -ms@^2.1.1: +ms@2.1.2, ms@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== @@ -8470,9 +8469,9 @@ postcss-lab-function@^2.0.1: postcss-values-parser "^2.0.0" postcss-load-config@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.1.0.tgz#c84d692b7bb7b41ddced94ee62e8ab31b417b003" - integrity sha512-4pV3JJVPLd5+RueiVVB+gFOAa7GWc25XQcMp86Zexzke69mKf6Nx9LRcQywdz7yZI9n1udOxmLuAwTBypypF8Q== + version "2.1.1" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.1.1.tgz#0a684bb8beb05e55baf922f7ab44c3edb17cf78e" + integrity sha512-D2ENobdoZsW0+BHy4x1CAkXtbXtYWYRIxL/JbtRBqrRGOPtJ2zoga/bEZWhV/ShWB5saVxJMzbMdSyA/vv4tXw== dependencies: cosmiconfig "^5.0.0" import-cwd "^2.0.0" @@ -8846,13 +8845,14 @@ postcss-selector-parser@^5.0.0-rc.3, postcss-selector-parser@^5.0.0-rc.4: uniq "^1.0.1" postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz#934cf799d016c83411859e09dcecade01286ec5c" - integrity sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg== + version "6.0.3" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.3.tgz#766d77728728817cc140fa1ac6da5e77f9fada98" + integrity sha512-0ClFaY4X1ra21LRqbW6y3rUbWcxnSVkDFG57R7Nxus9J9myPFlv+jYDMohzpkBx0RrjjiqjtycpchQ+PLGmZ9w== dependencies: cssesc "^3.0.0" indexes-of "^1.0.1" uniq "^1.0.1" + util-deprecate "^1.0.2" postcss-svgo@^4.0.2: version "4.0.2" @@ -8902,9 +8902,9 @@ postcss@7.0.21: supports-color "^6.1.0" postcss@^7, postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.23, postcss@^7.0.27, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6: - version "7.0.32" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.32.tgz#4310d6ee347053da3433db2be492883d62cec59d" - integrity sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw== + version "7.0.34" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.34.tgz#f2baf57c36010df7de4009940f21532c16d65c20" + integrity sha512-H/7V2VeNScX9KE83GDrDZNiGT1m2H+UTnlinIzhjlLX9hfMUn1mHNnGeX81a1c8JSBdBvqk7c2ZOG6ZPn5itGw== dependencies: chalk "^2.4.2" source-map "^0.6.1" @@ -9572,9 +9572,9 @@ regexpp@^3.0.0: integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== regexpu-core@^4.7.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.0.tgz#fcbf458c50431b0bb7b45d6967b8192d91f3d938" - integrity sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ== + version "4.7.1" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.1.tgz#2dea5a9a07233298fbf0db91fa9abc4c6e0f8ad6" + integrity sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ== dependencies: regenerate "^1.4.0" regenerate-unicode-properties "^8.2.0" @@ -10307,9 +10307,9 @@ spdx-expression-parse@^3.0.0: spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.5" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" - integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== + version "3.0.6" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz#c80757383c28abf7296744998cbc106ae8b854ce" + integrity sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw== spdy-transport@^3.0.0: version "3.0.0" @@ -11124,7 +11124,7 @@ use@^3.1.0: resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== -util-deprecate@^1.0.1, util-deprecate@~1.0.1: +util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= -- cgit v1.2.3-70-g09d2 From 44af615b32faf53c04cd38cb63782cf1b1332c94 Mon Sep 17 00:00:00 2001 From: Emiliano Ciavatta Date: Sat, 26 Sep 2020 12:05:27 +0200 Subject: General refactor --- frontend/package.json | 1 - frontend/src/backend.js | 38 ++-- frontend/src/components/fields/BooleanField.js | 37 ---- frontend/src/components/fields/BooleanField.scss | 34 ---- frontend/src/components/fields/CheckField.js | 36 ++++ frontend/src/components/fields/CheckField.scss | 35 ++++ frontend/src/components/fields/InputField.js | 75 +++++++ frontend/src/components/fields/InputField.scss | 147 ++++++++++++++ frontend/src/components/fields/StringField.js | 66 ------- frontend/src/components/fields/StringField.scss | 117 ----------- frontend/src/components/fields/TextField.js | 42 ++++ frontend/src/components/fields/TextField.scss | 79 ++++++++ .../components/filters/BooleanConnectionsFilter.js | 6 +- .../components/filters/StringConnectionsFilter.js | 8 +- frontend/src/components/panels/PcapPane.js | 86 ++++++-- frontend/src/components/panels/PcapPane.scss | 14 +- frontend/src/utils.js | 18 +- frontend/src/views/App.js | 12 +- frontend/src/views/Header.js | 5 +- frontend/src/views/Header.scss | 2 +- frontend/src/views/MainPane.js | 8 +- frontend/src/views/Services.js | 2 +- frontend/src/views/Upload.js | 218 --------------------- frontend/src/views/Upload.scss | 21 -- 24 files changed, 555 insertions(+), 552 deletions(-) delete mode 100644 frontend/src/components/fields/BooleanField.js delete mode 100644 frontend/src/components/fields/BooleanField.scss create mode 100644 frontend/src/components/fields/CheckField.js create mode 100644 frontend/src/components/fields/CheckField.scss create mode 100644 frontend/src/components/fields/InputField.js create mode 100644 frontend/src/components/fields/InputField.scss delete mode 100644 frontend/src/components/fields/StringField.js delete mode 100644 frontend/src/components/fields/StringField.scss create mode 100644 frontend/src/components/fields/TextField.js create mode 100644 frontend/src/components/fields/TextField.scss delete mode 100644 frontend/src/views/Upload.js delete mode 100644 frontend/src/views/Upload.scss diff --git a/frontend/package.json b/frontend/package.json index bf995c5..3629e70 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -9,7 +9,6 @@ "@testing-library/jest-dom": "^4.2.4", "@testing-library/react": "^9.3.2", "@testing-library/user-event": "^7.1.2", - "axios": "^0.19.2", "bootstrap": "^4.4.1", "bs-custom-file-input": "^1.3.4", "classnames": "^2.2.6", diff --git a/frontend/src/backend.js b/frontend/src/backend.js index 35ae6e3..5eb0e40 100644 --- a/frontend/src/backend.js +++ b/frontend/src/backend.js @@ -1,11 +1,11 @@ -async function request(method, url, data) { +async function json(method, url, data, headers) { const options = { method: method, mode: "cors", cache: "no-cache", credentials: "same-origin", - headers: { + headers: headers || { "Content-Type": "application/json" }, redirect: "follow", @@ -18,19 +18,35 @@ async function request(method, url, data) { return result.json(); } +async function file(url, data, headers) { + const options = { + method: "POST", + mode: "cors", + cache: "no-cache", + credentials: "same-origin", + body: data, + redirect: "follow", + referrerPolicy: "no-referrer", + }; + return await fetch(url, options); +} + const backend = { - get: (url = "") => { - return request("GET", url, null); + get: (url = "", headers = null) => { + return json("GET", url, null, headers); }, - post: (url = "", data = null) => { - return request("POST", url, data); + post: (url = "", data = null, headers = null) => { + return json("POST", url, data, headers); }, - put: (url = "", data = null) => { - return request("PUT", url, data); + put: (url = "", data = null, headers = null) => { + return json("PUT", url, data, headers); + }, + delete: (url = "", data = null, headers = null) => { + return json("DELETE", url, data, headers); + }, + postFile: (url = "", data = null, headers = null) => { + return file(url, data, headers); }, - delete: (url = "", data = null) => { - return request("DELETE", url, data); - } }; export default backend; diff --git a/frontend/src/components/fields/BooleanField.js b/frontend/src/components/fields/BooleanField.js deleted file mode 100644 index 06a6da7..0000000 --- a/frontend/src/components/fields/BooleanField.js +++ /dev/null @@ -1,37 +0,0 @@ -import React, {Component} from 'react'; -import './BooleanField.scss'; -import {randomClassName} from "../../utils"; - -const classNames = require('classnames'); - -class BooleanField extends Component { - - constructor(props) { - super(props); - - this.id = `field-${this.props.name || "noname"}-${randomClassName()}`; - } - - render() { - - const checked = this.props.checked || false; - const small = this.props.small || false; - const name = this.props.name || null; - const handler = () => { - if (this.props.onChange) { - this.props.onChange(!checked); - } - }; - - return ( -
-
- - -
-
- ); - } -} - -export default BooleanField; diff --git a/frontend/src/components/fields/BooleanField.scss b/frontend/src/components/fields/BooleanField.scss deleted file mode 100644 index 6ec25f7..0000000 --- a/frontend/src/components/fields/BooleanField.scss +++ /dev/null @@ -1,34 +0,0 @@ -@import '../../colors.scss'; - -.boolean-field { - font-size: 0.9em; - - .field-input { - border-radius: 5px; - width: fit-content; - background-color: $color-primary-2; - - input { - display: none; - } - - label { - margin: 0; - padding: 6px 15px; - cursor: pointer; - } - - &:hover { - background-color: $color-primary-1; - } - } - - &.field-checked .field-input { - background-color: $color-primary-4 !important; - color: $color-primary-3; - } - - &.field-small { - font-size: 0.8em; - } -} diff --git a/frontend/src/components/fields/CheckField.js b/frontend/src/components/fields/CheckField.js new file mode 100644 index 0000000..5cceac4 --- /dev/null +++ b/frontend/src/components/fields/CheckField.js @@ -0,0 +1,36 @@ +import React, {Component} from 'react'; +import './CheckField.scss'; +import {randomClassName} from "../../utils"; + +const classNames = require('classnames'); + +class CheckField extends Component { + + constructor(props) { + super(props); + + this.id = `field-${this.props.name || "noname"}-${randomClassName()}`; + } + + render() { + const checked = this.props.checked || false; + const small = this.props.small || false; + const name = this.props.name || null; + const handler = () => { + if (this.props.onChange) { + this.props.onChange(!checked); + } + }; + + return ( +
+
+ + +
+
+ ); + } +} + +export default CheckField; diff --git a/frontend/src/components/fields/CheckField.scss b/frontend/src/components/fields/CheckField.scss new file mode 100644 index 0000000..7b0ac5f --- /dev/null +++ b/frontend/src/components/fields/CheckField.scss @@ -0,0 +1,35 @@ +@import '../../colors.scss'; + +.check-field { + font-size: 0.9em; + margin: 5px 0; + + .field-input { + border-radius: 5px; + width: fit-content; + background-color: $color-primary-2; + + input { + display: none; + } + + label { + margin: 0; + padding: 6px 15px; + cursor: pointer; + } + + &:hover { + background-color: $color-primary-1; + } + } + + &.field-checked .field-input { + background-color: $color-primary-4 !important; + color: $color-primary-3; + } + + &.field-small { + font-size: 0.8em; + } +} diff --git a/frontend/src/components/fields/InputField.js b/frontend/src/components/fields/InputField.js new file mode 100644 index 0000000..af3b3df --- /dev/null +++ b/frontend/src/components/fields/InputField.js @@ -0,0 +1,75 @@ +import React, {Component} from 'react'; +import './InputField.scss'; +import {randomClassName} from "../../utils"; + +const classNames = require('classnames'); + +class InputField extends Component { + + constructor(props) { + super(props); + + this.id = `field-${this.props.name || "noname"}-${randomClassName()}`; + } + + render() { + const active = this.props.active || false; + const invalid = this.props.invalid || false; + const small = this.props.small || false; + const inline = this.props.inline || false; + const name = this.props.name || null; + const value = this.props.value || ""; + const type = this.props.type || "text"; + const error = this.props.error || null; + const defaultValue = this.props.defaultValue || null; + const handler = (e) => { + if (this.props.onChange) { + if (type === "file") { + let file = e.target.files[0]; + this.props.onChange(file); + } else if (e == null) { + this.props.onChange(""); + } else { + this.props.onChange(e.target.value); + } + } + }; + let inputProps = {}; + if (type !== "file") { + inputProps["value"] = value; + } + + return ( +
+
+ { name && +
+ +
+ } +
+
+ { type === "file" && } + +
+ { type !== "file" && value !== "" && +
+ handler(null)}>del +
+ } +
+
+ {error && +
+ error: {error} +
+ } +
+ ); + } +} + +export default InputField; diff --git a/frontend/src/components/fields/InputField.scss b/frontend/src/components/fields/InputField.scss new file mode 100644 index 0000000..cdb8c9f --- /dev/null +++ b/frontend/src/components/fields/InputField.scss @@ -0,0 +1,147 @@ +@import '../../colors.scss'; + +.input-field { + font-size: 0.9em; + margin: 5px 0; + + .field-name { + label { + margin: 0; + } + } + + .field-input { + position: relative; + + .field-value { + input, .file-label { + background-color: $color-primary-2; + width: 100%; + border: none; + color: $color-primary-4; + border-radius: 5px; + padding: 7px 10px; + + &:focus { + background-color: $color-primary-1; + color: $color-primary-4; + box-shadow: none; + outline: none; + } + + &[readonly] { + background-color: $color-primary-2; + border: none; + color: $color-primary-4; + } + + &[readonly]:focus { + background-color: $color-primary-1; + color: $color-primary-4; + box-shadow: none; + } + } + + input[type="file"] { + display: none; + } + + .file-label { + margin: 0; + } + + .file-label:after { + content: "Browse"; + position: absolute; + right: 0; + top: 0; + padding: 7px 10px 7px 12px; + background-color: $color-primary-1; + border-bottom-right-radius: 5px; + border-top-right-radius: 5px; + } + } + } + + &.field-active { + &.field-inline .field-name { + background-color: $color-primary-4 !important; + color: $color-primary-3 !important; + } + + .field-value input, .field-value .file-label { + background-color: $color-primary-4 !important; + color: $color-primary-3 !important; + } + + .file-label:after { + background-color: $color-secondary-4 !important; + } + } + + &.field-invalid { + &.field-inline .field-name { + background-color: $color-secondary-2 !important; + color: $color-primary-4 !important; + } + + .field-value input, .field-value .file-label { + background-color: $color-secondary-2 !important; + color: $color-primary-4 !important; + } + + .file-label:after { + background-color: $color-secondary-1 !important; + } + } + + &.field-small { + font-size: 0.8em; + } + + &.field-inline .field-wrapper { + display: flex; + + .field-name { + background-color: $color-primary-2; + padding: 6px 7px; + border-top-left-radius: 5px; + border-bottom-left-radius: 5px; + } + + .field-input { + width: 100%; + + input, .file-label { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + padding-left: 3px; + } + } + + &:focus-within .field-name { + background-color: $color-primary-1; + } + } + + .field-clear { + position: absolute; + right: 8px; + top: 8px; + z-index: 10; + font-size: 0.9em; + font-weight: 600; + letter-spacing: -0.5px; + cursor: pointer; + } + + &.field-active .field-clear { + color: $color-primary-2; + } + + .field-error { + padding: 5px 10px; + font-size: 0.9em; + color: $color-secondary-0; + } +} diff --git a/frontend/src/components/fields/StringField.js b/frontend/src/components/fields/StringField.js deleted file mode 100644 index 7781b2d..0000000 --- a/frontend/src/components/fields/StringField.js +++ /dev/null @@ -1,66 +0,0 @@ -import React, {Component} from 'react'; -import './StringField.scss'; -import {randomClassName} from "../../utils"; - -const classNames = require('classnames'); - -class StringField extends Component { - - constructor(props) { - super(props); - - this.id = `field-${this.props.name || "noname"}-${randomClassName()}`; - } - - render() { - - const active = this.props.active || false; - const invalid = this.props.invalid || false; - const small = this.props.small || false; - const inline = this.props.inline || false; - const name = this.props.name || null; - const value = this.props.value || ""; - const type = this.props.type || "text"; - const error = this.props.error || null; - const handler = (e) => { - if (this.props.onChange) { - if (e == null) { - this.props.onChange(""); - } else { - this.props.onChange(e.target.value); - } - } - }; - - return ( -
-
- { name && -
- -
- } -
-
- -
- { value !== "" && -
- handler(null)}>del -
- } -
-
- {error && -
- error: {error} -
- } -
- ); - } -} - -export default StringField; diff --git a/frontend/src/components/fields/StringField.scss b/frontend/src/components/fields/StringField.scss deleted file mode 100644 index 2523c8d..0000000 --- a/frontend/src/components/fields/StringField.scss +++ /dev/null @@ -1,117 +0,0 @@ -@import '../../colors.scss'; - -.string-field { - font-size: 0.9em; - - .field-name { - label { - margin: 0; - } - } - - .field-input { - position: relative; - - .field-value input { - background-color: $color-primary-2; - width: 100%; - border: none; - color: $color-primary-4; - border-radius: 5px; - padding: 7px 10px; - - &:focus { - background-color: $color-primary-1; - color: $color-primary-4; - box-shadow: none; - outline: none; - } - - &[readonly] { - background-color: $color-primary-2; - border: none; - color: $color-primary-4; - } - - &[readonly]:focus { - background-color: $color-primary-1; - color: $color-primary-4; - box-shadow: none; - } - } - } - - &.field-active { - &.field-inline .field-name { - background-color: $color-primary-4 !important; - color: $color-primary-3 !important; - } - - .field-value input { - background-color: $color-primary-4 !important; - color: $color-primary-3 !important; - } - } - - &.field-invalid { - &.field-inline .field-name { - background-color: $color-secondary-2 !important; - color: $color-primary-4 !important; - } - - .field-value input { - background-color: $color-secondary-2 !important; - color: $color-primary-4 !important; - } - } - - &.field-small { - font-size: 0.8em; - } - - &.field-inline .field-wrapper { - display: flex; - - .field-name { - background-color: $color-primary-2; - padding: 6px 7px; - border-top-left-radius: 5px; - border-bottom-left-radius: 5px; - } - - .field-input { - width: 100%; - - input { - border-bottom-left-radius: 0; - border-top-left-radius: 0; - padding-left: 3px; - } - } - - &:focus-within .field-name { - background-color: $color-primary-1; - } - } - - .field-clear { - position: absolute; - right: 8px; - top: 8px; - z-index: 10; - font-size: 0.9em; - font-weight: 600; - letter-spacing: -0.5px; - cursor: pointer; - } - - &.field-active .field-clear { - color: $color-primary-2; - } - - .field-error { - padding: 5px 10px; - font-size: 0.9em; - color: $color-secondary-0; - } -} diff --git a/frontend/src/components/fields/TextField.js b/frontend/src/components/fields/TextField.js new file mode 100644 index 0000000..86b98ed --- /dev/null +++ b/frontend/src/components/fields/TextField.js @@ -0,0 +1,42 @@ +import React, {Component} from 'react'; +import './TextField.scss'; +import {randomClassName} from "../../utils"; + +const classNames = require('classnames'); + +class TextField extends Component { + + constructor(props) { + super(props); + + this.id = `field-${this.props.name || "noname"}-${randomClassName()}`; + } + + render() { + const name = this.props.name || null; + const error = this.props.error || null; + const rows = this.props.rows || 3; + + const handler = (e) => { + if (this.props.onChange) { + if (e == null) { + this.props.onChange(""); + } else { + this.props.onChange(e.target.value); + } + } + }; + + return ( +
+ {name && } +