feat(ui): allow saving custom filter set as default

This commit is contained in:
Łukasz Mierzwa
2018-07-19 15:32:43 +02:00
parent ded8c77912
commit be3c8ef0c0
5 changed files with 111 additions and 15 deletions

View File

@@ -4,6 +4,7 @@ import PropTypes from "prop-types";
import { Provider } from "mobx-react";
import { AlertStore, DecodeLocationSearch } from "Stores/AlertStore";
import { Settings } from "Stores/Settings";
import { NavBar } from "Components/NavBar";
import { Grid } from "Components/Grid";
import { Fetcher } from "Components/Fetcher";
@@ -20,6 +21,8 @@ class App extends Component {
const { defaultFilters } = this.props;
this.settingsStore = new Settings();
let filters;
// parse and decode request query args
@@ -27,8 +30,12 @@ class App extends Component {
// p.defaultsUsed means that unsee URI didn't have ?q=foo query args
if (p.defaultsUsed) {
// no ?q=foo set, use defaults from backend config
filters = defaultFilters;
// no ?q=foo set, use defaults saved by the user or from backend config
if (this.settingsStore.savedFilters.present) {
filters = this.settingsStore.savedFilters.filters;
} else {
filters = defaultFilters;
}
} else {
// user passed ?q=foo, use it as initial filters
filters = p.params.q;
@@ -40,7 +47,10 @@ class App extends Component {
render() {
return (
<React.Fragment>
<NavBar alertStore={this.alertStore} />
<NavBar
alertStore={this.alertStore}
settingsStore={this.settingsStore}
/>
<Provider alertStore={this.alertStore}>
<Grid alertStore={this.alertStore} />
</Provider>

View File

@@ -10,8 +10,12 @@ import onClickOutside from "react-onclickoutside";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faCaretDown } from "@fortawesome/free-solid-svg-icons/faCaretDown";
import { faSave } from "@fortawesome/free-regular-svg-icons/faSave";
import { faUndoAlt } from "@fortawesome/free-solid-svg-icons/faUndoAlt";
import { faTrash } from "@fortawesome/free-solid-svg-icons/faTrash";
import { AlertStore } from "Stores/AlertStore";
import { Settings } from "Stores/Settings";
import { HistoryLabel } from "Components/Labels/HistoryLabel";
const defaultHistory = {
@@ -36,7 +40,9 @@ const HistoryMenu = onClickOutside(
popperStyle,
filters,
alertStore,
afterClick
settingsStore,
afterClick,
onClear
}) => {
return (
<div
@@ -70,6 +76,38 @@ const HistoryMenu = onClickOutside(
</button>
))
)}
<div className="dropdown-divider" />
<div className="container text-center">
<button className="btn btn-sm btn-success mr-4">
<FontAwesomeIcon
icon={faSave}
onClick={() => {
settingsStore.saveFilters(
alertStore.filters.values.map(f => f.raw)
);
afterClick();
}}
/>
</button>
<button
className="btn btn-sm btn-danger mr-4"
onClick={() => {
settingsStore.clearSavedFilters();
afterClick();
}}
>
<FontAwesomeIcon icon={faUndoAlt} />
</button>
<button
className="btn btn-sm btn-dark"
onClick={() => {
onClear();
afterClick();
}}
>
<FontAwesomeIcon icon={faTrash} />
</button>
</div>
</div>
);
}
@@ -80,13 +118,16 @@ HistoryMenu.propTypes = {
popperStyle: PropTypes.object,
filters: PropTypes.array.isRequired,
alertStore: PropTypes.instanceOf(AlertStore).isRequired,
afterClick: PropTypes.func.isRequired
settingsStore: PropTypes.instanceOf(Settings).isRequired,
afterClick: PropTypes.func.isRequired,
onClear: PropTypes.func.isRequired
};
const History = observer(
class History extends Component {
static propTypes = {
alertStore: PropTypes.instanceOf(AlertStore).isRequired
alertStore: PropTypes.instanceOf(AlertStore).isRequired,
settingsStore: PropTypes.instanceOf(Settings).isRequired
};
// how many filter sets do we store in local storage and render in the
@@ -137,6 +178,10 @@ const History = observer(
this.history.filters = newHistory;
});
clearHistory = action(() => {
this.history.filters = [];
});
componentDidUpdate() {
// every time this component updates we will rewrite history
// (if there are changes)
@@ -148,7 +193,7 @@ const History = observer(
});
render() {
const { alertStore } = this.props;
const { alertStore, settingsStore } = this.props;
return (
// data-filters is there to register filters for observation in mobx
@@ -189,7 +234,9 @@ const History = observer(
popperRef={ref}
popperStyle={style}
filters={this.history.filters}
onClear={this.clearHistory}
alertStore={alertStore}
settingsStore={settingsStore}
afterClick={this.collapse.hide}
handleClickOutside={this.collapse.hide}
outsideClickIgnoreClass="components-navbar-history"

View File

@@ -14,6 +14,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faSearch } from "@fortawesome/free-solid-svg-icons/faSearch";
import { AlertStore, FormatUnseeBackendURI } from "Stores/AlertStore";
import { Settings } from "Stores/Settings";
import { FilterInputLabel } from "Components/Labels/FilterInputLabel";
import { AutosuggestTheme } from "./Constants";
import { History } from "./History";
@@ -23,7 +24,8 @@ import "./index.css";
const FilterInput = observer(
class FilterInput extends Component {
static propTypes = {
alertStore: PropTypes.instanceOf(AlertStore).isRequired
alertStore: PropTypes.instanceOf(AlertStore).isRequired,
settingsStore: PropTypes.instanceOf(Settings).isRequired
};
inputStore = observable(
@@ -103,7 +105,12 @@ const FilterInput = observer(
};
renderInputComponent = inputProps => {
var { inputReference, alertStore, ...otherProps } = inputProps;
var {
inputReference,
alertStore,
settingsStore,
...otherProps
} = inputProps;
return (
<div className="input-group input-group-sm mr-2">
@@ -132,14 +139,14 @@ const FilterInput = observer(
/>
</div>
<div className="input-group-append">
<History alertStore={alertStore} />
<History alertStore={alertStore} settingsStore={settingsStore} />
</div>
</div>
);
};
render() {
const { alertStore } = this.props;
const { alertStore, settingsStore } = this.props;
return (
// data-filters is there to register filters for observation in mobx
@@ -163,7 +170,8 @@ const FilterInput = observer(
value: this.inputStore.value,
onChange: this.onChange,
inputReference: this.inputStore.ref,
alertStore: alertStore
alertStore: alertStore,
settingsStore: settingsStore
}}
theme={AutosuggestTheme}
/>

View File

@@ -6,6 +6,7 @@ import { observer } from "mobx-react";
import ReactResizeDetector from "react-resize-detector";
import { AlertStore } from "Stores/AlertStore";
import { Settings } from "Stores/Settings";
import { FetchIndicator } from "./FetchIndicator";
import { FilterInput } from "./FilterInput";
import { MainModal } from "Components/MainModal";
@@ -19,11 +20,12 @@ const navbarResize = function(width, height) {
const NavBar = observer(
class NavBar extends Component {
static propTypes = {
alertStore: PropTypes.instanceOf(AlertStore).isRequired
alertStore: PropTypes.instanceOf(AlertStore).isRequired,
settingsStore: PropTypes.instanceOf(Settings).isRequired
};
render() {
const { alertStore } = this.props;
const { alertStore, settingsStore } = this.props;
return (
<div className="container">
<nav className="navbar fixed-top navbar-expand navbar-dark p-1 bg-primary-transparent">
@@ -32,7 +34,10 @@ const NavBar = observer(
{alertStore.info.totalAlerts}
<FetchIndicator status={alertStore.status.value.toString()} />
</span>
<FilterInput alertStore={alertStore} />
<FilterInput
alertStore={alertStore}
settingsStore={settingsStore}
/>
<MainModal />
</nav>
</div>

26
ui/src/Stores/Settings.js Normal file
View File

@@ -0,0 +1,26 @@
import { localStored } from "mobx-stored";
import { action } from "mobx";
const defaultSavedFilters = {
filters: [],
present: false
};
class Settings {
savedFilters = localStored("savedFilters", defaultSavedFilters, {
delay: 100
});
saveFilters = action(newFilters => {
this.savedFilters.filters = newFilters;
this.savedFilters.present = true;
});
clearSavedFilters = action(() => {
this.savedFilters.filters = [];
this.savedFilters.present = false;
});
}
export { Settings };