diff --git a/client/app/components/proptypes.js b/client/app/components/proptypes.js
index e491b36166..1a936e3282 100644
--- a/client/app/components/proptypes.js
+++ b/client/app/components/proptypes.js
@@ -65,6 +65,7 @@ export const Query = PropTypes.shape({
export const AlertOptions = PropTypes.shape({
column: PropTypes.string,
+ selector: PropTypes.oneOf(["first", "min", "max"]),
op: PropTypes.oneOf([">", ">=", "<", "<=", "==", "!="]),
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
custom_subject: PropTypes.string,
@@ -83,6 +84,7 @@ export const Alert = PropTypes.shape({
query: Query,
options: PropTypes.shape({
column: PropTypes.string,
+ selector: PropTypes.string,
op: PropTypes.string,
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
}).isRequired,
diff --git a/client/app/pages/alert/Alert.jsx b/client/app/pages/alert/Alert.jsx
index e54ebcb0e6..9aac679f9a 100644
--- a/client/app/pages/alert/Alert.jsx
+++ b/client/app/pages/alert/Alert.jsx
@@ -64,6 +64,7 @@ class Alert extends React.Component {
this.setState({
alert: {
options: {
+ selector: "first",
op: ">",
value: 1,
muted: false,
@@ -75,7 +76,7 @@ class Alert extends React.Component {
} else {
const { alertId } = this.props;
AlertService.get({ id: alertId })
- .then(alert => {
+ .then((alert) => {
if (this._isMounted) {
const canEdit = currentUser.canEdit(alert);
@@ -93,7 +94,7 @@ class Alert extends React.Component {
this.onQuerySelected(alert.query);
}
})
- .catch(error => {
+ .catch((error) => {
if (this._isMounted) {
this.props.onError(error);
}
@@ -112,7 +113,7 @@ class Alert extends React.Component {
alert.rearm = pendingRearm || null;
return AlertService.save(alert)
- .then(alert => {
+ .then((alert) => {
notification.success("Saved.");
navigateTo(`alerts/${alert.id}`, true);
this.setState({ alert, mode: MODES.VIEW });
@@ -122,7 +123,7 @@ class Alert extends React.Component {
});
};
- onQuerySelected = query => {
+ onQuerySelected = (query) => {
this.setState(({ alert }) => ({
alert: Object.assign(alert, { query }),
queryResult: null,
@@ -130,7 +131,7 @@ class Alert extends React.Component {
if (query) {
// get cached result for column names and values
- new QueryService(query).getQueryResultPromise().then(queryResult => {
+ new QueryService(query).getQueryResultPromise().then((queryResult) => {
if (this._isMounted) {
this.setState({ queryResult });
let { column } = this.state.alert.options;
@@ -146,18 +147,18 @@ class Alert extends React.Component {
}
};
- onNameChange = name => {
+ onNameChange = (name) => {
const { alert } = this.state;
this.setState({
alert: Object.assign(alert, { name }),
});
};
- onRearmChange = pendingRearm => {
+ onRearmChange = (pendingRearm) => {
this.setState({ pendingRearm });
};
- setAlertOptions = obj => {
+ setAlertOptions = (obj) => {
const { alert } = this.state;
const options = { ...alert.options, ...obj };
this.setState({
@@ -258,7 +259,7 @@ routes.register(
routeWithUserSession({
path: "/alerts/new",
title: "New Alert",
- render: pageProps => ,
+ render: (pageProps) => ,
})
);
routes.register(
@@ -266,7 +267,7 @@ routes.register(
routeWithUserSession({
path: "/alerts/:alertId",
title: "Alert",
- render: pageProps => ,
+ render: (pageProps) => ,
})
);
routes.register(
@@ -274,6 +275,6 @@ routes.register(
routeWithUserSession({
path: "/alerts/:alertId/edit",
title: "Alert",
- render: pageProps => ,
+ render: (pageProps) => ,
})
);
diff --git a/client/app/pages/alert/components/Criteria.jsx b/client/app/pages/alert/components/Criteria.jsx
index 672aa86814..644e5d87e6 100644
--- a/client/app/pages/alert/components/Criteria.jsx
+++ b/client/app/pages/alert/components/Criteria.jsx
@@ -54,23 +54,70 @@ export default function Criteria({ columnNames, resultValues, alertOptions, onCh
return null;
})();
- const columnHint = (
-
- Top row value is {toString(columnValue) || "unknown"}
-
- );
+ let columnHint;
+
+ if (alertOptions.selector === "first") {
+ columnHint = (
+
+ Top row value is {toString(columnValue) || "unknown"}
+
+ );
+ } else if (alertOptions.selector === "max") {
+ columnHint = (
+
+ Max column value is{" "}
+
+ {toString(Math.max(...resultValues.map((o) => o[alertOptions.column]))) || "unknown"}
+
+
+ );
+ } else if (alertOptions.selector === "min") {
+ columnHint = (
+
+ Min column value is{" "}
+
+ {toString(Math.min(...resultValues.map((o) => o[alertOptions.column]))) || "unknown"}
+
+
+ );
+ }
return (
+
+ Selector
+ {editMode ? (
+
+ ) : (
+ {alertOptions.selector}
+ )}
+
Value column
{editMode ? (
@@ -83,10 +130,11 @@ export default function Criteria({ columnNames, resultValues, alertOptions, onCh
{editMode ? (