diff --git a/docs/DataStructure.md b/docs/DataStructure.md index a0f894d12..aa557cf8b 100644 --- a/docs/DataStructure.md +++ b/docs/DataStructure.md @@ -308,9 +308,11 @@ Supported trigger types for conditional questions: | `multiple_unique` | `option_selected` | Radio buttons - the selected option | | `dropdown` | `option_selected` | Dropdown - the selected option | | `multiple` | `options_combination` | Checkboxes - all options of a combination | +| `linearscale` | `value_equals`, `value_not_equals`, `value_range`, `value_min`, `value_max` | Linear scale - numeric value matching | | `date` | `date_range` | Date - range including its bounds (`YYYY-MM-DD`) | | `datetime` | `date_range` | Deprecated date and time (`YYYY-MM-DD HH:mm`) | | `time` | `date_range` | Time - range including its bounds (`HH:mm`) | +| `color` | `value_equals` | Color - exact value, ignoring case | | `file` | `file_uploaded` | File - whether a file was uploaded | A branch is shown when any of its conditions matches. Several branches can be shown at once. @@ -361,6 +363,24 @@ Conditions determine when a branch is activated. The structure depends on the tr All options in `optionIds` must be selected for the condition to match. +#### value_equals, value_not_equals (for linearscale), value_equals (for color) + +```json +{ "type": "value_equals", "value": 3 } +``` + +```json +{ "type": "value_equals", "value": "#ff0000" } +``` + +#### value_range, value_min, value_max (for linearscale) + +```json +{ "type": "value_range", "min": 3, "max": 5 } +``` + +`value_min` only uses `min`, `value_max` only uses `max`. + #### date_range (for date, datetime, time) ```json diff --git a/lib/Constants.php b/lib/Constants.php index f156f6039..31690f596 100644 --- a/lib/Constants.php +++ b/lib/Constants.php @@ -261,6 +261,11 @@ class Constants { */ public const CONDITION_TYPE_OPTION_SELECTED = 'option_selected'; public const CONDITION_TYPE_OPTIONS_COMBINATION = 'options_combination'; + public const CONDITION_TYPE_VALUE_EQUALS = 'value_equals'; + public const CONDITION_TYPE_VALUE_NOT_EQUALS = 'value_not_equals'; + public const CONDITION_TYPE_VALUE_RANGE = 'value_range'; + public const CONDITION_TYPE_VALUE_MIN = 'value_min'; + public const CONDITION_TYPE_VALUE_MAX = 'value_max'; public const CONDITION_TYPE_DATE_RANGE = 'date_range'; public const CONDITION_TYPE_FILE_UPLOADED = 'file_uploaded'; @@ -272,9 +277,11 @@ class Constants { self::ANSWER_TYPE_MULTIPLEUNIQUE => [self::CONDITION_TYPE_OPTION_SELECTED], self::ANSWER_TYPE_DROPDOWN => [self::CONDITION_TYPE_OPTION_SELECTED], self::ANSWER_TYPE_MULTIPLE => [self::CONDITION_TYPE_OPTIONS_COMBINATION], + self::ANSWER_TYPE_LINEARSCALE => [self::CONDITION_TYPE_VALUE_EQUALS, self::CONDITION_TYPE_VALUE_NOT_EQUALS, self::CONDITION_TYPE_VALUE_RANGE, self::CONDITION_TYPE_VALUE_MIN, self::CONDITION_TYPE_VALUE_MAX], self::ANSWER_TYPE_DATE => [self::CONDITION_TYPE_DATE_RANGE], self::ANSWER_TYPE_DATETIME => [self::CONDITION_TYPE_DATE_RANGE], self::ANSWER_TYPE_TIME => [self::CONDITION_TYPE_DATE_RANGE], + self::ANSWER_TYPE_COLOR => [self::CONDITION_TYPE_VALUE_EQUALS], self::ANSWER_TYPE_FILE => [self::CONDITION_TYPE_FILE_UPLOADED], ]; diff --git a/lib/Service/SubmissionService.php b/lib/Service/SubmissionService.php index 4a796402c..4f0b97618 100644 --- a/lib/Service/SubmissionService.php +++ b/lib/Service/SubmissionService.php @@ -1159,6 +1159,45 @@ private function evaluateBranchConditions(string $triggerType, array $triggerAns } } return false; + case Constants::ANSWER_TYPE_LINEARSCALE: + $numValue = (float)($triggerAnswer[0] ?? 0); + foreach ($conditions as $condition) { + $type = $condition['type'] ?? Constants::CONDITION_TYPE_VALUE_EQUALS; + if ($type === Constants::CONDITION_TYPE_VALUE_EQUALS) { + if ($numValue == (float)($condition['value'] ?? 0)) { + return true; + } + } elseif ($type === Constants::CONDITION_TYPE_VALUE_NOT_EQUALS) { + if ($numValue != (float)($condition['value'] ?? 0)) { + return true; + } + } elseif ($type === Constants::CONDITION_TYPE_VALUE_RANGE) { + $min = $condition['min'] ?? -PHP_FLOAT_MAX; + $max = $condition['max'] ?? PHP_FLOAT_MAX; + if ($numValue >= $min && $numValue <= $max) { + return true; + } + } elseif ($type === Constants::CONDITION_TYPE_VALUE_MIN) { + $min = $condition['min'] ?? -PHP_FLOAT_MAX; + if ($numValue >= $min) { + return true; + } + } elseif ($type === Constants::CONDITION_TYPE_VALUE_MAX) { + $max = $condition['max'] ?? PHP_FLOAT_MAX; + if ($numValue <= $max) { + return true; + } + } + } + return false; + case Constants::ANSWER_TYPE_COLOR: + $colorValue = is_scalar($triggerAnswer[0] ?? null) ? (string)$triggerAnswer[0] : ''; + foreach ($conditions as $condition) { + if (strcasecmp($colorValue, $condition['value'] ?? '') === 0) { + return true; + } + } + return false; case Constants::ANSWER_TYPE_FILE: $hasFile = !empty($triggerAnswer); foreach ($conditions as $condition) { diff --git a/src/components/Questions/BranchConditionEditor.vue b/src/components/Questions/BranchConditionEditor.vue index 26c5959c5..e6ea37aa5 100644 --- a/src/components/Questions/BranchConditionEditor.vue +++ b/src/components/Questions/BranchConditionEditor.vue @@ -32,6 +32,80 @@ + + +