aboutsummaryrefslogtreecommitdiff
path: root/frontend/src/components/filters
diff options
context:
space:
mode:
authorVaiTon2023-06-05 14:54:12 +0000
committerVaiTon2023-06-05 14:54:12 +0000
commit2e6af3b2623da3d002816a6de325133d626858c9 (patch)
tree69448ca3dc33f8754fa88ffa77ed3dea524848b5 /frontend/src/components/filters
parentf4c97974dac97f3254047fd17abed09e82cae797 (diff)
Frontend to jsx
Diffstat (limited to 'frontend/src/components/filters')
-rw-r--r--frontend/src/components/filters/AdvancedFilters.jsx54
-rw-r--r--frontend/src/components/filters/BooleanConnectionsFilter.jsx69
-rw-r--r--frontend/src/components/filters/ExitSearchFilter.jsx57
-rw-r--r--frontend/src/components/filters/RulesConnectionsFilter.jsx83
-rw-r--r--frontend/src/components/filters/StringConnectionsFilter.jsx127
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);