From 876d74517cc8f8316b38215efd59a63cbe95cee7 Mon Sep 17 00:00:00 2001
From: raviks789 <raviks789@gmail.com>
Date: Tue, 23 Apr 2024 12:15:33 +0200
Subject: [PATCH] Make fields for incident age condition intuitive

---
 .../EscalationCondition.php                   | 47 ++++++++++---------
 application/forms/EventRuleConfigForm.php     | 11 ++++-
 .../ItemList/EscalationConditionListItem.php  | 12 +++++
 public/css/event-rule-config.less             | 12 +++++
 4 files changed, 59 insertions(+), 23 deletions(-)

diff --git a/application/forms/EventRuleConfigElements/EscalationCondition.php b/application/forms/EventRuleConfigElements/EscalationCondition.php
index cf46b4b8b..749cb527b 100644
--- a/application/forms/EventRuleConfigElements/EscalationCondition.php
+++ b/application/forms/EventRuleConfigElements/EscalationCondition.php
@@ -10,7 +10,6 @@
 use ipl\Html\FormElement\FieldsetElement;
 use ipl\Html\FormElement\SubmitButtonElement;
 use ipl\Stdlib\Filter;
-use ipl\Validator\CallbackValidator;
 use ipl\Web\Filter\QueryString;
 use ipl\Web\Widget\Icon;
 
@@ -112,6 +111,7 @@ protected function assemble(): void
             );
 
             $valName = 'val_' . $i;
+            $valUnit = null;
             switch ($this->getPopulatedValue('column_' . $i)) {
                 case 'incident_severity':
                     $val = $this->createElement(
@@ -136,28 +136,22 @@ protected function assemble(): void
                     break;
                 case 'incident_age':
                     $val = $this->createElement(
-                        'text',
+                        'number',
                         $valName,
                         [
                             'required'   => true,
-                            'class'      => ['autosubmit', 'right-operand'],
-                            'validators' => [
-                                new CallbackValidator(function ($value, $validator) {
-                                    if (! preg_match('~^\d+(?:\.?\d*)?[hms]{1}$~', $value)) {
-                                        $validator->addMessage(
-                                            $this->translate(
-                                                'Only numbers with optional fractions (separated by a dot)'
-                                                . ' and one of these suffixes are allowed: h, m, s'
-                                            )
-                                        );
-
-                                        return false;
-                                    }
-
-                                    $validator->clearMessages();
-                                    return true;
-                                })
-                            ]
+                            'class'      => 'right-operand',
+                            'step'       => 0.5,
+                            'value'      => 1
+                        ]
+                    );
+
+                    $valUnit = $this->createElement(
+                        'select',
+                        'unit_' . $i,
+                        [
+                            'options' => ['m' => 'm', 'h' => 'h'],
+                            'class'   => ['autosubmit', 'unit']
                         ]
                     );
 
@@ -173,6 +167,14 @@ protected function assemble(): void
             $this->registerElement($col);
             $this->registerElement($op);
             $this->registerElement($val);
+            if ($valUnit) {
+                $this->registerElement($valUnit);
+                $unit = $valUnit->getValue();
+                $value = $val->getValue();
+                $val->getAttributes()->set('min', $unit === 'm' ? 1 : 0.5);
+                $val->getAttributes()->set('value', $unit === 'm' && (float) $value === 0.5 ? 1 : $value);
+            }
+
             $removeButton = null;
 
             if (($conditionCount > 1) || ($conditionCount === 1 && ! $configHasZeroConditionEscalation)) {
@@ -183,7 +185,7 @@ protected function assemble(): void
             }
 
             (new EventRuleDecorator())->decorate($val);
-            $this->conditions[$i] = new EscalationConditionListItem($i, $col, $op, $val, $removeButton);
+            $this->conditions[$i] = new EscalationConditionListItem($i, $col, $op, $val, $valUnit, $removeButton);
         }
 
         if ($removePosition) {
@@ -256,7 +258,8 @@ public function getCondition(): string
 
             $filterStr = $chosenType
                 . $this->getValue('operator_' . $count)
-                . ($this->getValue('val_' . $count) ?? ($chosenType === 'incident_severity' ? 'ok' : ''));
+                . ($this->getValue('val_' . $count) ?? ($chosenType === 'incident_severity' ? 'ok' : ''))
+                . $this->getValue('unit_' . $count, '');
 
             $filter->add(QueryString::parse($filterStr));
         }
diff --git a/application/forms/EventRuleConfigForm.php b/application/forms/EventRuleConfigForm.php
index 1f7f8617a..572dcdc85 100644
--- a/application/forms/EventRuleConfigForm.php
+++ b/application/forms/EventRuleConfigForm.php
@@ -289,7 +289,16 @@ public function populate($values): self
                 }
 
                 $conditionFormValues['operator_' . $count] = QueryString::getRuleSymbol($filter);
-                $conditionFormValues['val_' . $count] = $filter->getValue();
+                $conditionValue = $filter->getValue();
+                if (
+                    preg_match('~^(\d+(?:\.?\d*))?([hms])$~', $conditionValue, $matches)
+                    && count($matches) === 3
+                ) {
+                    $conditionFormValues['val_' . $count] = $matches[1];
+                    $conditionFormValues['unit_' . $count] = $matches[2];
+                } else {
+                    $conditionFormValues['val_' . $count] = $conditionValue;
+                }
             }
 
             $formValues['escalation-condition_' . bin2hex($position)] = $conditionFormValues;
diff --git a/library/Notifications/Widget/ItemList/EscalationConditionListItem.php b/library/Notifications/Widget/ItemList/EscalationConditionListItem.php
index 0c9917944..6389c1395 100644
--- a/library/Notifications/Widget/ItemList/EscalationConditionListItem.php
+++ b/library/Notifications/Widget/ItemList/EscalationConditionListItem.php
@@ -29,12 +29,16 @@ class EscalationConditionListItem extends BaseHtmlElement
     /** @var int */
     protected $position;
 
+    /** @var ?FormElement Unit of the condition value */
+    protected $conditionUnit;
+
     /**
      * Create the condition list item of the escalation
      *
      * @param FormElement $conditionType
      * @param FormElement $operator
      * @param FormElement $conditionVal
+     * @param ?FormElement $conditionUnit,
      * @param ?SubmitButtonElement $removeButton
      */
     public function __construct(
@@ -42,12 +46,14 @@ public function __construct(
         FormElement $conditionType,
         FormElement $operator,
         FormElement $conditionVal,
+        ?FormElement $conditionUnit,
         ?SubmitButtonElement $removeButton
     ) {
         $this->position = $position;
         $this->conditionType = $conditionType;
         $this->operator = $operator;
         $this->conditionVal = $conditionVal;
+        $this->conditionUnit = $conditionUnit;
         $this->removeButton = $removeButton;
     }
 
@@ -89,6 +95,12 @@ protected function assemble(): void
         $this->conditionVal->setAttribute('name', 'val_' . $this->position);
 
         $this->addHtml($this->conditionType, $this->operator, $this->conditionVal);
+
+        if ($this->conditionUnit) {
+            $this->conditionUnit->setAttribute('name', 'unit_' . $this->position);
+            $this->addHtml($this->conditionUnit->setAttribute('name', 'unit_' . $this->position));
+        }
+
         if ($this->removeButton) {
             $this->removeButton->setSubmitValue((string) $this->position);
             $this->addHtml($this->removeButton);
diff --git a/public/css/event-rule-config.less b/public/css/event-rule-config.less
index a631d708c..01d95decc 100644
--- a/public/css/event-rule-config.less
+++ b/public/css/event-rule-config.less
@@ -176,6 +176,12 @@
           margin: 0;
         }
 
+        .unit {
+          border-radius: 0 0.4em 0.4em 0;;
+          min-width: 3.5em;
+          margin-left: 1px;
+        }
+
         .errors + .remove-button {
           margin: 0;
         }
@@ -239,6 +245,12 @@
   margin-right: 1px;
 }
 
+// <(needed pixel size)/(font size)>em Readjust number type input element's minimum width in escalation condition
+.escalation-condition .options input[type='number'] {
+  border-radius: 0;
+  min-width: 77/12em;
+}
+
 .escalation-condition,
 .escalation-recipient {
   .options + .add-button,