diff --git a/backend/README.md b/backend/README.md index bcf1dec..2ca1217 100644 --- a/backend/README.md +++ b/backend/README.md @@ -29,6 +29,10 @@ To run celery queue processing: celery worker -A appenlight.celery -Q "reports,logs,metrics,default" --ini=development.ini +To run celery beats scheduling: + + celery beat -A appenlight.celery --ini=development.ini + You should also run the channelstream websocket server for real-time notifications channelstream -i filename.ini diff --git a/backend/src/appenlight/lib/rule.py b/backend/src/appenlight/lib/rule.py index b7d4fd5..a0c99e8 100644 --- a/backend/src/appenlight/lib/rule.py +++ b/backend/src/appenlight/lib/rule.py @@ -188,6 +188,10 @@ class Rule(RuleBase): rule = OR(self.config['rules'], self.type_matrix, config_manipulator=self.config_manipulator) return rule.match(struct) + elif field_name == '__NOT__': + rule = NOT(self.config['rules'], self.type_matrix, + config_manipulator=self.config_manipulator) + return rule.match(struct) if test_value is None: return False @@ -236,6 +240,16 @@ class AND(Rule): in self.rules]) +class NOT(Rule): + def __init__(self, rules, *args, **kwargs): + super(NOT, self).__init__({}, *args, **kwargs) + self.rules = rules + + def match(self, struct): + return all([not self.subrule_check(r_conf, struct) for r_conf + in self.rules]) + + class OR(Rule): def __init__(self, rules, *args, **kwargs): super(OR, self).__init__({}, *args, **kwargs) @@ -266,7 +280,8 @@ class RuleService(object): if manipulator_func is None: def label_rewriter_func(rule): field = rule.config.get('field') - if not field or rule.config['field'] in ['__OR__', '__AND__']: + if not field or rule.config['field'] in ['__OR__', + '__AND__', '__NOT__']: return to_map = field_mappings.get(rule.config['field']) diff --git a/backend/src/appenlight/static/js/appenlight.js b/backend/src/appenlight/static/js/appenlight.js index d457b1c..16081e4 100644 --- a/backend/src/appenlight/static/js/appenlight.js +++ b/backend/src/appenlight/static/js/appenlight.js @@ -5376,11 +5376,11 @@ function kickstartAE() { " {{rule_ctrlr.readOnlyPossibleFields[rule_ctrlr.rule.field]}}\n" + " \n" + "\n" + - " \n" + + " \n" + " is {{rule_ctrlr.ruleDefinitions.allOps[rule_ctrlr.rule.op]}} {{rule_ctrlr.rule.value}}\n" + " \n" + "\n" + - " \n" + + " \n" + "

Subrules

\n" + "
\n" + "\n" + @@ -5408,7 +5408,7 @@ function kickstartAE() { " ng-options=\"key as label for (key, label) in rule_ctrlr.ruleDefinitions.possibleFields\">\n" + "
\n" + "\n" + - "
\n" + + "
\n" + "\n" + "
-
+