From c8628ed84062dece9b2bd2383b63c7654c501f9f Mon Sep 17 00:00:00 2001 From: formsdev <136701234+formsdev@users.noreply.github.com> Date: Tue, 19 Mar 2024 19:57:21 +0530 Subject: [PATCH] Separate input type for Rating,Scale,Slider (#351) * Separate input type for Rating,Scale,Slider * rating, scale, slider add in test cases * Allow field type change for new types * Added options to db factory * Fix linting --------- Co-authored-by: Julien Nahum --- app/Console/Commands/GenerateTemplate.php | 71 +-- app/Console/Commands/InputNumberMigration.php | 69 +++ app/Http/Requests/AnswerFormRequest.php | 39 +- app/Jobs/Form/GenerateAiForm.php | 12 +- app/Rules/FormPropertyLogicRule.php | 209 +++++++- .../Forms/FormLogicConditionChecker.php | 51 +- client/components/global/Dropdown.vue | 6 + .../components/open/forms/OpenFormField.vue | 131 ++--- .../form-components/AddFormBlock.vue | 72 ++- .../form-logic-components/ColumnCondition.vue | 36 +- .../open/forms/fields/FormFieldEdit.vue | 2 +- .../fields/components/ChangeFieldType.vue | 10 +- .../forms/fields/components/FieldOptions.vue | 484 +++++++----------- client/components/open/tables/OpenTable.vue | 137 +++-- client/composables/forms/initForm.js | 2 - client/data/open_filters.json | 174 +++++++ client/lib/forms/FormLogicConditionChecker.js | 3 + resources/data/open_filters.json | 174 +++++++ tests/Helpers/FormSubmissionDataFactory.php | 7 + tests/TestHelpers.php | 27 +- 20 files changed, 1104 insertions(+), 612 deletions(-) create mode 100644 app/Console/Commands/InputNumberMigration.php diff --git a/app/Console/Commands/GenerateTemplate.php b/app/Console/Commands/GenerateTemplate.php index 63accadd..9cfff1b9 100644 --- a/app/Console/Commands/GenerateTemplate.php +++ b/app/Console/Commands/GenerateTemplate.php @@ -108,7 +108,7 @@ class GenerateTemplate extends Command "color": "#64748b" } ``` - The form properties can only have one of the following types: 'text', 'number', 'select', 'multi_select', 'date', 'files', 'checkbox', 'url', 'email', 'phone_number', 'signature'. + The form properties can only have one of the following types: 'text', 'number', 'rating', 'scale','slider', 'select', 'multi_select', 'date', 'files', 'checkbox', 'url', 'email', 'phone_number', 'signature'. All form properties objects need to have the keys 'help', 'name', 'type', 'hidden', 'placeholder', 'prefill'. The placeholder property is optional (can be "null") and is used to display a placeholder text in the input field. The help property is optional (can be "null") and is used to display extra information about the field. @@ -125,14 +125,9 @@ class GenerateTemplate extends Command } ``` - For numerical rating inputs, use a "number" type input and set the property "is_rating" to "true" to turn it into a star rating input. Ex: - ```json - { - "name":"How would you rate your overall experience?", - "type":"number", - "is_rating": true - } - ``` + For "rating" you can set the field property "rating_max_value" to set the maximum value of the rating. + For "scale" you can set the field property "scale_min_value", "scale_max_value" and "scale_step_value" to set the minimum, maximum and step value of the scale. + For "slider" you can set the field property "slider_min_value", "slider_max_value" and "slider_step_value" to set the minimum, maximum and step value of the slider. If the form is too long, you can paginate it by adding a page break block in the list of properties: ```json @@ -230,6 +225,7 @@ class GenerateTemplate extends Command ['role' => 'user', 'content' => Str::of(self::FORM_STRUCTURE_PROMPT)->replace('[REPLACE]', $this->argument('prompt'))->toString()], ]); $formData = $completer->getArray(); + $formData = self::cleanAiOutput($formData); $completer->doesNotExpectJson(); $formDescriptionPrompt = Str::of(self::FORM_DESCRIPTION_PROMPT)->replace('[REPLACE]', $this->argument('prompt'))->toString(); @@ -284,7 +280,7 @@ class GenerateTemplate extends Command $types, $relatedTemplates ); - $this->info('/form-templates/'.$template->slug); + $this->info('/form-templates/' . $template->slug); // Set reverse related Templates $this->setReverseRelatedTemplates($template); @@ -297,7 +293,7 @@ class GenerateTemplate extends Command */ private function getImageCoverUrl($searchQuery): ?string { - $url = 'https://api.unsplash.com/search/photos?query='.urlencode($searchQuery).'&client_id='.config('services.unsplash.access_key'); + $url = 'https://api.unsplash.com/search/photos?query=' . urlencode($searchQuery) . '&client_id=' . config('services.unsplash.access_key'); $response = Http::get($url)->json(); $photoIndex = rand(0, max(count($response['results']) - 1, 10)); if (isset($response['results'][$photoIndex]['urls']['regular'])) { @@ -333,7 +329,6 @@ class GenerateTemplate extends Command private function getRelatedTemplates(array $industries, array $types): array { - ray($industries, $types); $templateScore = []; Template::chunk(100, function ($otherTemplates) use ($industries, $types, &$templateScore) { foreach ($otherTemplates as $otherTemplate) { @@ -361,24 +356,6 @@ class GenerateTemplate extends Command array $types, array $relatedTemplates ) { - // Add property uuids, improve form with options - foreach ($formData['properties'] as &$property) { - $property['id'] = Str::uuid()->toString(); // Column ID - - // Fix ratings - if ($property['type'] == 'number' && ($property['is_rating'] ?? false)) { - $property['rating_max_value'] = 5; - } - - if (($property['type'] == 'select' && count($property['select']['options']) <= 4) - || ($property['type'] == 'multi_select' && count($property['multi_select']['options']) <= 4)) { - $property['without_dropdown'] = true; - } - } - - // Clean data - $formTitle = Str::of($formTitle)->replace('"', '')->toString(); - return Template::create([ 'name' => $formTitle, 'description' => $formDescription, @@ -395,7 +372,7 @@ class GenerateTemplate extends Command private function setReverseRelatedTemplates(Template $newTemplate) { - if (! $newTemplate || count($newTemplate->related_templates) === 0) { + if (!$newTemplate || count($newTemplate->related_templates) === 0) { return; } @@ -406,4 +383,36 @@ class GenerateTemplate extends Command } } } + + public static function cleanAiOutput(array $formData): array + { + // Add property uuids, improve form with options + foreach ($formData['properties'] as &$property) { + $property['id'] = Str::uuid()->toString(); // Column ID + + // Fix types + if ($property['type'] == 'rating') { + $property['rating_max_value'] = $property['rating_max_value'] ?? 5; + } elseif ($property['type'] == 'scale') { + $property['scale_min_value'] = $property['scale_min_value'] ?? 1; + $property['scale_max_value'] = $property['scale_max_value'] ?? 5; + $property['scale_step_value'] = $property['scale_step_value'] ?? 1; + } elseif ($property['type'] == 'slider') { + $property['slider_min_value'] = $property['slider_min_value'] ?? 0; + $property['slider_max_value'] = $property['slider_max_value'] ?? 100; + $property['slider_step_value'] = $property['slider_step_value'] ?? 1; + } + + if (($property['type'] == 'select' && count($property['select']['options']) <= 4) + || ($property['type'] == 'multi_select' && count($property['multi_select']['options']) <= 4) + ) { + $property['without_dropdown'] = true; + } + } + + // Clean data + $formData['title'] = Str::of($formData['title'])->replace('"', '')->toString(); + + return $formData; + } } diff --git a/app/Console/Commands/InputNumberMigration.php b/app/Console/Commands/InputNumberMigration.php new file mode 100644 index 00000000..c0a0c5f2 --- /dev/null +++ b/app/Console/Commands/InputNumberMigration.php @@ -0,0 +1,69 @@ +line('Process For Form: ' . $form->id . ' - ' . $form->slug); + + $form->properties = collect($form->properties)->map(function ($property) { + if ($property['type'] === 'number') { + // Rating + if (isset($property['is_rating']) && $property['is_rating']) { + $this->line('Rating Field'); + $property['type'] = 'rating'; + unset($property['is_rating']); + } + + // Scale + if (isset($property['is_scale']) && $property['is_scale']) { + $this->line('Scale Field'); + $property['type'] = 'scale'; + unset($property['is_scale']); + } + + // Slider + if (isset($property['is_slider']) && $property['is_slider']) { + $this->line('Slider Field'); + $property['type'] = 'slider'; + unset($property['is_slider']); + } + } + return $property; + })->toArray(); + $form->update(); + } + } + ); + + $this->line('Migration Done'); + } +} diff --git a/app/Http/Requests/AnswerFormRequest.php b/app/Http/Requests/AnswerFormRequest.php index c1f8f9c1..508ed853 100644 --- a/app/Http/Requests/AnswerFormRequest.php +++ b/app/Http/Requests/AnswerFormRequest.php @@ -40,7 +40,7 @@ class AnswerFormRequest extends FormRequest */ public function authorize() { - return ! $this->form->is_closed && ! $this->form->max_number_of_submissions_reached && $this->form->visibility === 'public'; + return !$this->form->is_closed && !$this->form->max_number_of_submissions_reached && $this->form->visibility === 'public'; } /** @@ -79,7 +79,7 @@ class AnswerFormRequest extends FormRequest if ($property['type'] == 'checkbox') { // Required for checkboxes means true $rules[] = 'accepted'; - } elseif ($property['type'] == 'number' && isset($property['is_rating']) && $property['is_rating']) { + } elseif ($property['type'] == 'rating') { // For star rating, needs a minimum of 1 star $rules[] = 'min:1'; } @@ -91,7 +91,7 @@ class AnswerFormRequest extends FormRequest $propertyId = $property['id']; if (in_array($property['type'], ['multi_select'])) { $rules[] = 'array'; - $this->requestRules[$propertyId.'.*'] = $this->getPropertyRules($property); + $this->requestRules[$propertyId . '.*'] = $this->getPropertyRules($property); } else { $rules = array_merge($rules, $this->getPropertyRules($property)); } @@ -137,12 +137,12 @@ class AnswerFormRequest extends FormRequest $messages = []; foreach ($this->form->properties as $property) { if ($property['type'] == 'date' && isset($property['date_range']) && $property['date_range']) { - $messages[$property['id'].'.0.required_with'] = 'From date is required'; - $messages[$property['id'].'.1.required_with'] = 'To date is required'; - $messages[$property['id'].'.0.before_or_equal'] = 'From date must be before or equal To date'; + $messages[$property['id'] . '.0.required_with'] = 'From date is required'; + $messages[$property['id'] . '.1.required_with'] = 'To date is required'; + $messages[$property['id'] . '.0.before_or_equal'] = 'From date must be before or equal To date'; } - if ($property['type'] == 'number' && isset($property['is_rating']) && $property['is_rating']) { - $messages[$property['id'].'.min'] = 'A rating must be selected'; + if ($property['type'] == 'rating') { + $messages[$property['id'] . '.min'] = 'A rating must be selected'; } } @@ -159,10 +159,9 @@ class AnswerFormRequest extends FormRequest case 'signature': return ['string']; case 'number': - if ($property['is_rating'] ?? false) { - return ['numeric']; - } - + case 'rating': + case 'scale': + case 'slider': return ['numeric']; case 'select': case 'multi_select': @@ -175,7 +174,7 @@ class AnswerFormRequest extends FormRequest return ['boolean']; case 'url': if (isset($property['file_upload']) && $property['file_upload']) { - $this->requestRules[$property['id'].'.*'] = [new StorageFile($this->maxFileSize, [], $this->form)]; + $this->requestRules[$property['id'] . '.*'] = [new StorageFile($this->maxFileSize, [], $this->form)]; return ['array']; } @@ -183,7 +182,7 @@ class AnswerFormRequest extends FormRequest return [new ValidUrl()]; case 'files': $allowedFileTypes = []; - if (! empty($property['allowed_file_types'])) { + if (!empty($property['allowed_file_types'])) { $allowedFileTypes = explode(',', $property['allowed_file_types']); } $this->requestRules[$property['id'] . '.*'] = [new StorageFile($this->getFieldMaxFileSize($property), $allowedFileTypes, $this->form)]; @@ -193,9 +192,9 @@ class AnswerFormRequest extends FormRequest return ['email:filter']; case 'date': if (isset($property['date_range']) && $property['date_range']) { - $this->requestRules[$property['id'].'.*'] = $this->getRulesForDate($property); - $this->requestRules[$property['id'].'.0'] = ['required_with:'.$property['id'].'.1', 'before_or_equal:'.$property['id'].'.1']; - $this->requestRules[$property['id'].'.1'] = ['required_with:'.$property['id'].'.0']; + $this->requestRules[$property['id'] . '.*'] = $this->getRulesForDate($property); + $this->requestRules[$property['id'] . '.0'] = ['required_with:' . $property['id'] . '.1', 'before_or_equal:' . $property['id'] . '.1']; + $this->requestRules[$property['id'] . '.1'] = ['required_with:' . $property['id'] . '.0']; return ['array', 'min:2']; } @@ -226,7 +225,7 @@ class AnswerFormRequest extends FormRequest private function getSelectPropertyOptions($property): array { $type = $property['type']; - if (! isset($property[$type])) { + if (!isset($property[$type])) { return []; } @@ -242,7 +241,7 @@ class AnswerFormRequest extends FormRequest $receivedValue = $receivedData[$property['id']] ?? null; // Escape all '\' in select options - if (in_array($property['type'], ['select', 'multi_select']) && ! is_null($receivedValue)) { + if (in_array($property['type'], ['select', 'multi_select']) && !is_null($receivedValue)) { if (is_array($receivedValue)) { $mergeData[$property['id']] = collect($receivedValue)->map(function ($value) { $value = Str::of($value); @@ -261,7 +260,7 @@ class AnswerFormRequest extends FormRequest } } - if ($property['type'] === 'phone_number' && (! isset($property['use_simple_text_input']) || ! $property['use_simple_text_input']) && $receivedValue && in_array($receivedValue, $countryCodeMapper)) { + if ($property['type'] === 'phone_number' && (!isset($property['use_simple_text_input']) || !$property['use_simple_text_input']) && $receivedValue && in_array($receivedValue, $countryCodeMapper)) { $mergeData[$property['id']] = null; } }); diff --git a/app/Jobs/Form/GenerateAiForm.php b/app/Jobs/Form/GenerateAiForm.php index c0560ef9..9d397c55 100644 --- a/app/Jobs/Form/GenerateAiForm.php +++ b/app/Jobs/Form/GenerateAiForm.php @@ -53,7 +53,7 @@ class GenerateAiForm implements ShouldQueue $this->completion->update([ 'status' => AiFormCompletion::STATUS_COMPLETED, - 'result' => $this->cleanOutput($completer->getArray()), + 'result' => GenerateTemplate::cleanAiOutput($completer->getArray()) ]); } catch (\Exception $e) { $this->onError($e); @@ -61,16 +61,6 @@ class GenerateAiForm implements ShouldQueue } - private function cleanOutput($formData) - { - // Add property uuids - foreach ($formData['properties'] as &$property) { - $property['id'] = Str::uuid()->toString(); - } - - return $formData; - } - /** * Handle a job failure. */ diff --git a/app/Rules/FormPropertyLogicRule.php b/app/Rules/FormPropertyLogicRule.php index 8d46a993..6398b927 100644 --- a/app/Rules/FormPropertyLogicRule.php +++ b/app/Rules/FormPropertyLogicRule.php @@ -288,6 +288,168 @@ class FormPropertyLogicRule implements DataAwareRule, Rule ], ], ], + 'rating' => [ + 'comparators' => [ + 'equals' => [ + 'expected_type' => 'number', + ], + 'does_not_equal' => [ + 'expected_type' => 'number', + ], + 'greater_than' => [ + 'expected_type' => 'number', + ], + 'less_than' => [ + 'expected_type' => 'number', + ], + 'greater_than_or_equal_to' => [ + 'expected_type' => 'number', + ], + 'less_than_or_equal_to' => [ + 'expected_type' => 'number', + ], + 'is_empty' => [ + 'expected_type' => 'boolean', + 'format' => [ + 'type' => 'enum', + 'values' => [true], + ], + ], + 'is_not_empty' => [ + 'expected_type' => 'boolean', + 'format' => [ + 'type' => 'enum', + 'values' => [true], + ], + ], + 'content_length_equals' => [ + 'expected_type' => 'number', + ], + 'content_length_does_not_equal' => [ + 'expected_type' => 'number', + ], + 'content_length_greater_than' => [ + 'expected_type' => 'number', + ], + 'content_length_greater_than_or_equal_to' => [ + 'expected_type' => 'number', + ], + 'content_length_less_than' => [ + 'expected_type' => 'number', + ], + 'content_length_less_than_or_equal_to' => [ + 'expected_type' => 'number', + ], + ], + ], + 'scale' => [ + 'comparators' => [ + 'equals' => [ + 'expected_type' => 'number', + ], + 'does_not_equal' => [ + 'expected_type' => 'number', + ], + 'greater_than' => [ + 'expected_type' => 'number', + ], + 'less_than' => [ + 'expected_type' => 'number', + ], + 'greater_than_or_equal_to' => [ + 'expected_type' => 'number', + ], + 'less_than_or_equal_to' => [ + 'expected_type' => 'number', + ], + 'is_empty' => [ + 'expected_type' => 'boolean', + 'format' => [ + 'type' => 'enum', + 'values' => [true], + ], + ], + 'is_not_empty' => [ + 'expected_type' => 'boolean', + 'format' => [ + 'type' => 'enum', + 'values' => [true], + ], + ], + 'content_length_equals' => [ + 'expected_type' => 'number', + ], + 'content_length_does_not_equal' => [ + 'expected_type' => 'number', + ], + 'content_length_greater_than' => [ + 'expected_type' => 'number', + ], + 'content_length_greater_than_or_equal_to' => [ + 'expected_type' => 'number', + ], + 'content_length_less_than' => [ + 'expected_type' => 'number', + ], + 'content_length_less_than_or_equal_to' => [ + 'expected_type' => 'number', + ], + ], + ], + 'slider' => [ + 'comparators' => [ + 'equals' => [ + 'expected_type' => 'number', + ], + 'does_not_equal' => [ + 'expected_type' => 'number', + ], + 'greater_than' => [ + 'expected_type' => 'number', + ], + 'less_than' => [ + 'expected_type' => 'number', + ], + 'greater_than_or_equal_to' => [ + 'expected_type' => 'number', + ], + 'less_than_or_equal_to' => [ + 'expected_type' => 'number', + ], + 'is_empty' => [ + 'expected_type' => 'boolean', + 'format' => [ + 'type' => 'enum', + 'values' => [true], + ], + ], + 'is_not_empty' => [ + 'expected_type' => 'boolean', + 'format' => [ + 'type' => 'enum', + 'values' => [true], + ], + ], + 'content_length_equals' => [ + 'expected_type' => 'number', + ], + 'content_length_does_not_equal' => [ + 'expected_type' => 'number', + ], + 'content_length_greater_than' => [ + 'expected_type' => 'number', + ], + 'content_length_greater_than_or_equal_to' => [ + 'expected_type' => 'number', + ], + 'content_length_less_than' => [ + 'expected_type' => 'number', + ], + 'content_length_less_than_or_equal_to' => [ + 'expected_type' => 'number', + ], + ], + ], 'checkbox' => [ 'comparators' => [ 'equals' => [ @@ -484,35 +646,35 @@ class FormPropertyLogicRule implements DataAwareRule, Rule private function checkBaseCondition($condition) { - if (! isset($condition['value'])) { + if (!isset($condition['value'])) { $this->isConditionCorrect = false; $this->conditionErrors[] = 'missing condition body'; return; } - if (! isset($condition['value']['property_meta'])) { + if (!isset($condition['value']['property_meta'])) { $this->isConditionCorrect = false; $this->conditionErrors[] = 'missing condition property'; return; } - if (! isset($condition['value']['property_meta']['type'])) { + if (!isset($condition['value']['property_meta']['type'])) { $this->isConditionCorrect = false; $this->conditionErrors[] = 'missing condition property type'; return; } - if (! isset($condition['value']['operator'])) { + if (!isset($condition['value']['operator'])) { $this->isConditionCorrect = false; $this->conditionErrors[] = 'missing condition operator'; return; } - if (! isset($condition['value']['value'])) { + if (!isset($condition['value']['value'])) { $this->isConditionCorrect = false; $this->conditionErrors[] = 'missing condition value'; @@ -523,14 +685,14 @@ class FormPropertyLogicRule implements DataAwareRule, Rule $operator = $condition['value']['operator']; $value = $condition['value']['value']; - if (! isset(self::CONDITION_MAPPING[$typeField])) { + if (!isset(self::CONDITION_MAPPING[$typeField])) { $this->isConditionCorrect = false; $this->conditionErrors[] = 'configuration not found for condition type'; return; } - if (! isset(self::CONDITION_MAPPING[$typeField]['comparators'][$operator])) { + if (!isset(self::CONDITION_MAPPING[$typeField]['comparators'][$operator])) { $this->isConditionCorrect = false; $this->conditionErrors[] = 'configuration not found for condition operator'; @@ -546,11 +708,11 @@ class FormPropertyLogicRule implements DataAwareRule, Rule $foundCorrectType = true; } } - if (! $foundCorrectType) { + if (!$foundCorrectType) { $this->isConditionCorrect = false; } } else { - if (! $this->valueHasCorrectType($type, $value)) { + if (!$this->valueHasCorrectType($type, $value)) { $this->isConditionCorrect = false; $this->conditionErrors[] = 'wrong type of condition value'; } @@ -561,9 +723,9 @@ class FormPropertyLogicRule implements DataAwareRule, Rule { if ( ($type === 'string' && gettype($value) !== 'string') || - ($type === 'boolean' && ! is_bool($value)) || - ($type === 'number' && ! is_numeric($value)) || - ($type === 'object' && ! is_array($value)) + ($type === 'boolean' && !is_bool($value)) || + ($type === 'number' && !is_numeric($value)) || + ($type === 'object' && !is_array($value)) ) { return false; } @@ -588,7 +750,7 @@ class FormPropertyLogicRule implements DataAwareRule, Rule return; } - if (! is_array($conditions['children'])) { + if (!is_array($conditions['children'])) { $this->conditionErrors[] = 'wrong sub-condition type'; $this->isConditionCorrect = false; @@ -607,11 +769,12 @@ class FormPropertyLogicRule implements DataAwareRule, Rule { if (is_array($actions) && count($actions) > 0) { foreach ($actions as $val) { - if (! in_array($val, static::ACTIONS_VALUES) || - (in_array($this->field['type'], ['nf-text', 'nf-code', 'nf-page-break', 'nf-divider', 'nf-image']) && ! in_array($val, ['hide-block', 'show-block'])) || - (isset($this->field['hidden']) && $this->field['hidden'] && ! in_array($val, ['show-block', 'require-answer'])) || - (isset($this->field['required']) && $this->field['required'] && ! in_array($val, ['make-it-optional', 'hide-block', 'disable-block'])) || - (isset($this->field['disabled']) && $this->field['disabled'] && ! in_array($val, ['enable-block', 'require-answer', 'make-it-optional'])) + if ( + !in_array($val, static::ACTIONS_VALUES) || + (in_array($this->field['type'], ['nf-text', 'nf-code', 'nf-page-break', 'nf-divider', 'nf-image']) && !in_array($val, ['hide-block', 'show-block'])) || + (isset($this->field['hidden']) && $this->field['hidden'] && !in_array($val, ['show-block', 'require-answer'])) || + (isset($this->field['required']) && $this->field['required'] && !in_array($val, ['make-it-optional', 'hide-block', 'disable-block'])) || + (isset($this->field['disabled']) && $this->field['disabled'] && !in_array($val, ['enable-block', 'require-answer', 'make-it-optional'])) ) { $this->isActionCorrect = false; break; @@ -646,13 +809,13 @@ class FormPropertyLogicRule implements DataAwareRule, Rule public function message() { $message = null; - if (! $this->isConditionCorrect) { - $message = 'The logic conditions for '.$this->field['name'].' are not complete.'; - } elseif (! $this->isActionCorrect) { - $message = 'The logic actions for '.$this->field['name'].' are not valid.'; + if (!$this->isConditionCorrect) { + $message = 'The logic conditions for ' . $this->field['name'] . ' are not complete.'; + } elseif (!$this->isActionCorrect) { + $message = 'The logic actions for ' . $this->field['name'] . ' are not valid.'; } if (count($this->conditionErrors) > 0) { - return $message.' Error detail(s): '.implode(', ', $this->conditionErrors); + return $message . ' Error detail(s): ' . implode(', ', $this->conditionErrors); } return $message; diff --git a/app/Service/Forms/FormLogicConditionChecker.php b/app/Service/Forms/FormLogicConditionChecker.php index 0d95f6b5..a7573859 100644 --- a/app/Service/Forms/FormLogicConditionChecker.php +++ b/app/Service/Forms/FormLogicConditionChecker.php @@ -15,19 +15,19 @@ class FormLogicConditionChecker private function conditionsAreMet(?array $conditions, array $formData): bool { - if (! $conditions) { + if (!$conditions) { return false; } // If it's not a group, just a single condition - if (! isset($conditions['operatorIdentifier'])) { + if (!isset($conditions['operatorIdentifier'])) { return $this->propertyConditionMet($conditions['value'], $formData[$conditions['value']['property_meta']['id']] ?? null); } if ($conditions['operatorIdentifier'] === 'and') { $isvalid = true; foreach ($conditions['children'] as $childrenCondition) { - if (! $this->conditionsMet($childrenCondition, $formData)) { + if (!$this->conditionsMet($childrenCondition, $formData)) { $isvalid = false; break; } @@ -46,7 +46,7 @@ class FormLogicConditionChecker return $isvalid; } - throw new \Exception('Unexcepted operatorIdentifier:'.$conditions['operatorIdentifier']); + throw new \Exception('Unexcepted operatorIdentifier:' . $conditions['operatorIdentifier']); } private function propertyConditionMet(array $propertyCondition, $value): bool @@ -58,6 +58,9 @@ class FormLogicConditionChecker case 'phone_number': return $this->textConditionMet($propertyCondition, $value); case 'number': + case 'rating': + case 'scale': + case 'slider': return $this->numberConditionMet($propertyCondition, $value); case 'checkbox': return $this->checkboxConditionMet($propertyCondition, $value); @@ -90,7 +93,7 @@ class FormLogicConditionChecker return false; } - if (! is_array($fieldValue)) { + if (!is_array($fieldValue)) { return $this->checkEquals($condition, $fieldValue); } @@ -117,7 +120,7 @@ class FormLogicConditionChecker return count($fieldValue) === 0; } - return $fieldValue == '' || $fieldValue == null || ! $fieldValue; + return $fieldValue == '' || $fieldValue == null || !$fieldValue; } private function checkGreaterThan($condition, $fieldValue): bool @@ -162,7 +165,7 @@ class FormLogicConditionChecker private function checkPastWeek($condition, $fieldValue): bool { - if (! $fieldValue) { + if (!$fieldValue) { return false; } $fieldDate = date('Y-m-d', strtotime($fieldValue)); @@ -172,7 +175,7 @@ class FormLogicConditionChecker private function checkPastMonth($condition, $fieldValue): bool { - if (! $fieldValue) { + if (!$fieldValue) { return false; } $fieldDate = date('Y-m-d', strtotime($fieldValue)); @@ -182,7 +185,7 @@ class FormLogicConditionChecker private function checkPastYear($condition, $fieldValue): bool { - if (! $fieldValue) { + if (!$fieldValue) { return false; } $fieldDate = date('Y-m-d', strtotime($fieldValue)); @@ -192,7 +195,7 @@ class FormLogicConditionChecker private function checkNextWeek($condition, $fieldValue): bool { - if (! $fieldValue) { + if (!$fieldValue) { return false; } $fieldDate = date('Y-m-d', strtotime($fieldValue)); @@ -202,7 +205,7 @@ class FormLogicConditionChecker private function checkNextMonth($condition, $fieldValue): bool { - if (! $fieldValue) { + if (!$fieldValue) { return false; } $fieldDate = date('Y-m-d', strtotime($fieldValue)); @@ -212,7 +215,7 @@ class FormLogicConditionChecker private function checkNextYear($condition, $fieldValue): bool { - if (! $fieldValue) { + if (!$fieldValue) { return false; } $fieldDate = date('Y-m-d', strtotime($fieldValue)); @@ -222,7 +225,7 @@ class FormLogicConditionChecker private function checkLength($condition, $fieldValue, $operator = '==='): bool { - if (! $fieldValue || strlen($fieldValue) === 0) { + if (!$fieldValue || strlen($fieldValue) === 0) { return false; } switch ($operator) { @@ -249,11 +252,11 @@ class FormLogicConditionChecker case 'equals': return $this->checkEquals($propertyCondition, $value); case 'does_not_equal': - return ! $this->checkEquals($propertyCondition, $value); + return !$this->checkEquals($propertyCondition, $value); case 'contains': return $this->checkContains($propertyCondition, $value); case 'does_not_contain': - return ! $this->checkContains($propertyCondition, $value); + return !$this->checkContains($propertyCondition, $value); case 'starts_with': return $this->checkStartsWith($propertyCondition, $value); case 'ends_with': @@ -261,7 +264,7 @@ class FormLogicConditionChecker case 'is_empty': return $this->checkIsEmpty($propertyCondition, $value); case 'is_not_empty': - return ! $this->checkIsEmpty($propertyCondition, $value); + return !$this->checkIsEmpty($propertyCondition, $value); case 'content_length_equals': return $this->checkLength($propertyCondition, $value, '==='); case 'content_length_does_not_equal': @@ -285,7 +288,7 @@ class FormLogicConditionChecker case 'equals': return $this->checkEquals($propertyCondition, $value); case 'does_not_equal': - return ! $this->checkEquals($propertyCondition, $value); + return !$this->checkEquals($propertyCondition, $value); case 'greater_than': return $this->checkGreaterThan($propertyCondition, $value); case 'less_than': @@ -297,7 +300,7 @@ class FormLogicConditionChecker case 'is_empty': return $this->checkIsEmpty($propertyCondition, $value); case 'is_not_empty': - return ! $this->checkIsEmpty($propertyCondition, $value); + return !$this->checkIsEmpty($propertyCondition, $value); case 'content_length_equals': return $this->checkLength($propertyCondition, $value, '==='); case 'content_length_does_not_equal': @@ -321,7 +324,7 @@ class FormLogicConditionChecker case 'equals': return $this->checkEquals($propertyCondition, $value); case 'does_not_equal': - return ! $this->checkEquals($propertyCondition, $value); + return !$this->checkEquals($propertyCondition, $value); } return false; @@ -333,11 +336,11 @@ class FormLogicConditionChecker case 'equals': return $this->checkEquals($propertyCondition, $value); case 'does_not_equal': - return ! $this->checkEquals($propertyCondition, $value); + return !$this->checkEquals($propertyCondition, $value); case 'is_empty': return $this->checkIsEmpty($propertyCondition, $value); case 'is_not_empty': - return ! $this->checkIsEmpty($propertyCondition, $value); + return !$this->checkIsEmpty($propertyCondition, $value); } return false; @@ -381,11 +384,11 @@ class FormLogicConditionChecker case 'contains': return $this->checkListContains($propertyCondition, $value); case 'does_not_contain': - return ! $this->checkListContains($propertyCondition, $value); + return !$this->checkListContains($propertyCondition, $value); case 'is_empty': return $this->checkIsEmpty($propertyCondition, $value); case 'is_not_empty': - return ! $this->checkIsEmpty($propertyCondition, $value); + return !$this->checkIsEmpty($propertyCondition, $value); } return false; @@ -397,7 +400,7 @@ class FormLogicConditionChecker case 'is_empty': return $this->checkIsEmpty($propertyCondition, $value); case 'is_not_empty': - return ! $this->checkIsEmpty($propertyCondition, $value); + return !$this->checkIsEmpty($propertyCondition, $value); } return false; diff --git a/client/components/global/Dropdown.vue b/client/components/global/Dropdown.vue index 3d64b5ee..f8c42142 100644 --- a/client/components/global/Dropdown.vue +++ b/client/components/global/Dropdown.vue @@ -46,4 +46,10 @@ const onClickAway = (event) => { close(event) } } + +defineExpose({ + open, + close, + toggle +}) diff --git a/client/components/open/forms/OpenFormField.vue b/client/components/open/forms/OpenFormField.vue index 5c1281f6..c18f442f 100644 --- a/client/components/open/forms/OpenFormField.vue +++ b/client/components/open/forms/OpenFormField.vue @@ -1,77 +1,52 @@