diff options
author | VaiTon | 2023-06-05 14:54:12 +0000 |
---|---|---|
committer | VaiTon | 2023-06-05 14:54:12 +0000 |
commit | 2e6af3b2623da3d002816a6de325133d626858c9 (patch) | |
tree | 69448ca3dc33f8754fa88ffa77ed3dea524848b5 /frontend/src/components/filters | |
parent | f4c97974dac97f3254047fd17abed09e82cae797 (diff) |
Frontend to jsx
Diffstat (limited to 'frontend/src/components/filters')
5 files changed, 390 insertions, 0 deletions
diff --git a/frontend/src/components/filters/AdvancedFilters.jsx b/frontend/src/components/filters/AdvancedFilters.jsx new file mode 100644 index 0000000..8598185 --- /dev/null +++ b/frontend/src/components/filters/AdvancedFilters.jsx @@ -0,0 +1,54 @@ +/* + * This file is part of caronte (https://github.com/eciavatta/caronte). + * Copyright (c) 2020 Emiliano Ciavatta. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import React, {Component} from "react"; +import {withRouter} from "react-router-dom"; +import dispatcher from "../../dispatcher"; +import {updateParams} from "../../utils"; +import ButtonField from "../fields/ButtonField"; + +class AdvancedFilters extends Component { + + state = {}; + + componentDidMount() { + this.urlParams = new URLSearchParams(this.props.location.search); + + this.connectionsFiltersCallback = (payload) => { + this.urlParams = updateParams(this.urlParams, payload); + const active = ["client_address", "client_port", "min_duration", "max_duration", "min_bytes", "max_bytes"] + .some((f) => this.urlParams.has(f)); + if (this.state.active !== active) { + this.setState({active}); + } + }; + dispatcher.register("connections_filters", this.connectionsFiltersCallback); + } + + componentWillUnmount() { + dispatcher.unregister(this.connectionsFiltersCallback); + } + + render() { + return ( + <ButtonField onClick={this.props.onClick} name="advanced_filters" small active={this.state.active}/> + ); + } + +} + +export default withRouter(AdvancedFilters); diff --git a/frontend/src/components/filters/BooleanConnectionsFilter.jsx b/frontend/src/components/filters/BooleanConnectionsFilter.jsx new file mode 100644 index 0000000..0355167 --- /dev/null +++ b/frontend/src/components/filters/BooleanConnectionsFilter.jsx @@ -0,0 +1,69 @@ +/* + * This file is part of caronte (https://github.com/eciavatta/caronte). + * Copyright (c) 2020 Emiliano Ciavatta. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import React, {Component} from "react"; +import {withRouter} from "react-router-dom"; +import dispatcher from "../../dispatcher"; +import CheckField from "../fields/CheckField"; + +class BooleanConnectionsFilter extends Component { + + state = { + filterActive: "false" + }; + + componentDidMount() { + let params = new URLSearchParams(this.props.location.search); + this.setState({filterActive: this.toBoolean(params.get(this.props.filterName)).toString()}); + + this.connectionsFiltersCallback = (payload) => { + const name = this.props.filterName; + if (name in payload && this.state.filterActive !== payload[name]) { + this.setState({filterActive: payload[name]}); + } + }; + dispatcher.register("connections_filters", this.connectionsFiltersCallback); + } + + componentWillUnmount() { + dispatcher.unregister(this.connectionsFiltersCallback); + } + + toBoolean = (value) => { + return value !== null && value.toLowerCase() === "true"; + }; + + filterChanged = () => { + const newValue = (!this.toBoolean(this.state.filterActive)).toString(); + const urlParams = {}; + urlParams[this.props.filterName] = newValue === "true" ? "true" : null; + dispatcher.dispatch("connections_filters", urlParams); + this.setState({filterActive: newValue}); + }; + + render() { + return ( + <div className="filter" style={{"width": `${this.props.width}px`}}> + <CheckField checked={this.toBoolean(this.state.filterActive)} name={this.props.filterName} + onChange={this.filterChanged} small/> + </div> + ); + } + +} + +export default withRouter(BooleanConnectionsFilter); diff --git a/frontend/src/components/filters/ExitSearchFilter.jsx b/frontend/src/components/filters/ExitSearchFilter.jsx new file mode 100644 index 0000000..0aacfd6 --- /dev/null +++ b/frontend/src/components/filters/ExitSearchFilter.jsx @@ -0,0 +1,57 @@ +/* + * This file is part of caronte (https://github.com/eciavatta/caronte). + * Copyright (c) 2020 Emiliano Ciavatta. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import React, {Component} from "react"; +import {withRouter} from "react-router-dom"; +import dispatcher from "../../dispatcher"; +import CheckField from "../fields/CheckField"; + +class ExitSearchFilter extends Component { + + state = {}; + + componentDidMount() { + let params = new URLSearchParams(this.props.location.search); + this.setState({performedSearch: params.get("performed_search")}); + + this.connectionsFiltersCallback = (payload) => { + if (this.state.performedSearch !== payload["performed_search"]) { + this.setState({performedSearch: payload["performed_search"]}); + } + }; + dispatcher.register("connections_filters", this.connectionsFiltersCallback); + } + + componentWillUnmount() { + dispatcher.unregister(this.connectionsFiltersCallback); + } + + render() { + return ( + <> + {this.state.performedSearch && + <div className="filter" style={{"width": `${this.props.width}px`}}> + <CheckField checked={true} name="exit_search" onChange={() => + dispatcher.dispatch("connections_filters", {"performed_search": null})} small/> + </div>} + </> + ); + } + +} + +export default withRouter(ExitSearchFilter); diff --git a/frontend/src/components/filters/RulesConnectionsFilter.jsx b/frontend/src/components/filters/RulesConnectionsFilter.jsx new file mode 100644 index 0000000..4ae769a --- /dev/null +++ b/frontend/src/components/filters/RulesConnectionsFilter.jsx @@ -0,0 +1,83 @@ +/* + * This file is part of caronte (https://github.com/eciavatta/caronte). + * Copyright (c) 2020 Emiliano Ciavatta. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import React, {Component} from "react"; +import {withRouter} from "react-router-dom"; +import backend from "../../backend"; +import dispatcher from "../../dispatcher"; +import TagField from "../fields/TagField"; + +import classNames from 'classnames'; +import _ from 'lodash'; + +class RulesConnectionsFilter extends Component { + + state = { + rules: [], + activeRules: [] + }; + + componentDidMount() { + const params = new URLSearchParams(this.props.location.search); + let activeRules = params.getAll("matched_rules") || []; + + backend.get("/api/rules").then((res) => { + let rules = res.json.flatMap((rule) => rule.enabled ? [{id: rule.id, name: rule.name}] : []); + activeRules = rules.filter((rule) => activeRules.some((id) => rule.id === id)); + this.setState({rules, activeRules}); + }); + + this.connectionsFiltersCallback = (payload) => { + if ("matched_rules" in payload && !_.isEqual(payload["matched_rules"].sort(), this.state.activeRules.sort())) { + const newRules = this.state.rules.filter((r) => payload["matched_rules"].includes(r.id)); + this.setState({ + activeRules: newRules.map((r) => { + return {id: r.id, name: r.name}; + }) + }); + } + }; + dispatcher.register("connections_filters", this.connectionsFiltersCallback); + } + + componentWillUnmount() { + dispatcher.unregister(this.connectionsFiltersCallback); + } + + onChange = (activeRules) => { + if (!_.isEqual(activeRules.sort(), this.state.activeRules.sort())) { + this.setState({activeRules}); + dispatcher.dispatch("connections_filters", {"matched_rules": activeRules.map((r) => r.id)}); + } + }; + + render() { + return ( + <div + className={classNames("filter", "d-inline-block", {"filter-active": this.state.filterActive === "true"})}> + <div className="filter-rules"> + <TagField tags={this.state.activeRules} onChange={this.onChange} + suggestions={_.differenceWith(this.state.rules, this.state.activeRules, _.isEqual)} + minQueryLength={0} name="matched_rules" inline small placeholder="rule_name"/> + </div> + </div> + ); + } + +} + +export default withRouter(RulesConnectionsFilter); diff --git a/frontend/src/components/filters/StringConnectionsFilter.jsx b/frontend/src/components/filters/StringConnectionsFilter.jsx new file mode 100644 index 0000000..c5d7075 --- /dev/null +++ b/frontend/src/components/filters/StringConnectionsFilter.jsx @@ -0,0 +1,127 @@ +/* + * This file is part of caronte (https://github.com/eciavatta/caronte). + * Copyright (c) 2020 Emiliano Ciavatta. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import React, {Component} from "react"; +import {withRouter} from "react-router-dom"; +import dispatcher from "../../dispatcher"; +import InputField from "../fields/InputField"; + +class StringConnectionsFilter extends Component { + + state = { + fieldValue: "", + filterValue: null, + timeoutHandle: null, + invalidValue: false + }; + + componentDidMount() { + let params = new URLSearchParams(this.props.location.search); + this.updateStateFromFilterValue(params.get(this.props.filterName)); + + this.connectionsFiltersCallback = (payload) => { + const name = this.props.filterName; + if (name in payload && this.state.filterValue !== payload[name]) { + this.updateStateFromFilterValue(payload[name]); + } + }; + dispatcher.register("connections_filters", this.connectionsFiltersCallback); + } + + componentWillUnmount() { + dispatcher.unregister(this.connectionsFiltersCallback); + } + + updateStateFromFilterValue = (filterValue) => { + if (filterValue !== null) { + let fieldValue = filterValue; + if (typeof this.props.decodeFunc === "function") { + fieldValue = this.props.decodeFunc(filterValue); + } + if (typeof this.props.replaceFunc === "function") { + fieldValue = this.props.replaceFunc(fieldValue); + } + if (this.isValueValid(fieldValue)) { + this.setState({fieldValue, filterValue}); + } else { + this.setState({fieldValue, invalidValue: true}); + } + } else { + this.setState({fieldValue: "", filterValue: null}); + } + }; + + isValueValid = (value) => { + return typeof this.props.validateFunc !== "function" || + (typeof this.props.validateFunc === "function" && this.props.validateFunc(value)); + }; + + changeFilterValue = (value) => { + const urlParams = {}; + urlParams[this.props.filterName] = value; + dispatcher.dispatch("connections_filters", urlParams); + }; + + filterChanged = (fieldValue) => { + if (this.state.timeoutHandle) { + clearTimeout(this.state.timeoutHandle); + } + + if (typeof this.props.replaceFunc === "function") { + fieldValue = this.props.replaceFunc(fieldValue); + } + + if (fieldValue === "") { + this.setState({fieldValue: "", filterValue: null, invalidValue: false}); + return this.changeFilterValue(null); + } + + + if (this.isValueValid(fieldValue)) { + let filterValue = fieldValue; + if (filterValue !== "" && typeof this.props.encodeFunc === "function") { + filterValue = this.props.encodeFunc(filterValue); + } + + this.setState({ + fieldValue, + timeoutHandle: setTimeout(() => { + this.setState({filterValue}); + this.changeFilterValue(filterValue); + }, 500), + invalidValue: false + }); + } else { + this.setState({fieldValue, invalidValue: true}); + } + }; + + render() { + let active = this.state.filterValue !== null; + + return ( + <div className="filter" style={{"width": `${this.props.width}px`}}> + <InputField active={active} invalid={this.state.invalidValue} name={this.props.filterName} + placeholder={this.props.defaultFilterValue} onChange={this.filterChanged} + value={this.state.fieldValue} inline={this.props.inline} small={this.props.small}/> + </div> + ); + } + +} + +export default withRouter(StringConnectionsFilter); |