Fix logic for multi select (#6)
* Fix logic for multi select * test case for multi select logic
This commit is contained in:
parent
ef70be9d14
commit
610c71cb69
|
@ -6,7 +6,8 @@ use Illuminate\Contracts\Validation\Rule;
|
||||||
use Illuminate\Contracts\Validation\DataAwareRule;
|
use Illuminate\Contracts\Validation\DataAwareRule;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
class FormPropertyLogicRule implements Rule, DataAwareRule {
|
class FormPropertyLogicRule implements Rule, DataAwareRule
|
||||||
|
{
|
||||||
|
|
||||||
const ACTIONS_VALUES = [
|
const ACTIONS_VALUES = [
|
||||||
'show-block',
|
'show-block',
|
||||||
|
@ -242,7 +243,7 @@ class FormPropertyLogicRule implements Rule, DataAwareRule {
|
||||||
'multi_select' => [
|
'multi_select' => [
|
||||||
'comparators' => [
|
'comparators' => [
|
||||||
'contains' => [
|
'contains' => [
|
||||||
'expected_type' => 'object',
|
'expected_type' => ['object', 'string'],
|
||||||
'format' => [
|
'format' => [
|
||||||
'type' => 'uuid',
|
'type' => 'uuid',
|
||||||
]
|
]
|
||||||
|
@ -384,36 +385,37 @@ class FormPropertyLogicRule implements Rule, DataAwareRule {
|
||||||
private $field = [];
|
private $field = [];
|
||||||
private $data = [];
|
private $data = [];
|
||||||
|
|
||||||
private function checkBaseCondition($condtion) {
|
private function checkBaseCondition($condition)
|
||||||
|
{
|
||||||
|
|
||||||
if (!isset($condtion['value'])) {
|
if (!isset($condition['value'])) {
|
||||||
$this->isConditionCorrect = false;
|
$this->isConditionCorrect = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isset($condtion['value']['property_meta'])) {
|
if (!isset($condition['value']['property_meta'])) {
|
||||||
$this->isConditionCorrect = false;
|
$this->isConditionCorrect = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isset($condtion['value']['property_meta']['type'])) {
|
if (!isset($condition['value']['property_meta']['type'])) {
|
||||||
$this->isConditionCorrect = false;
|
$this->isConditionCorrect = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isset($condtion['value']['operator'])) {
|
if (!isset($condition['value']['operator'])) {
|
||||||
$this->isConditionCorrect = false;
|
$this->isConditionCorrect = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isset($condtion['value']['value'])) {
|
if (!isset($condition['value']['value'])) {
|
||||||
$this->isConditionCorrect = false;
|
$this->isConditionCorrect = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$typeField = $condtion['value']['property_meta']['type'];
|
$typeField = $condition['value']['property_meta']['type'];
|
||||||
$operator = $condtion['value']['operator'];
|
$operator = $condition['value']['operator'];
|
||||||
$value = $condtion['value']['value'];
|
$value = $condition['value']['value'];
|
||||||
|
|
||||||
if (!isset(self::CONDITION_MAPPING[$typeField])) {
|
if (!isset(self::CONDITION_MAPPING[$typeField])) {
|
||||||
$this->isConditionCorrect = false;
|
$this->isConditionCorrect = false;
|
||||||
|
@ -427,18 +429,38 @@ class FormPropertyLogicRule implements Rule, DataAwareRule {
|
||||||
|
|
||||||
$type = self::CONDITION_MAPPING[$typeField]['comparators'][$operator]['expected_type'];
|
$type = self::CONDITION_MAPPING[$typeField]['comparators'][$operator]['expected_type'];
|
||||||
|
|
||||||
// Type d'objet : string, boolean, number, object
|
if (is_array($type)) {
|
||||||
|
$foundCorrectType = false;
|
||||||
|
foreach ($type as $subtype) {
|
||||||
|
if ($this->valueHasCorrectType($subtype, $value)) {
|
||||||
|
$foundCorrectType = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!$foundCorrectType) {
|
||||||
|
$this->isConditionCorrect = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!$this->valueHasCorrectType($type, $value)) {
|
||||||
|
$this->isConditionCorrect = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function valueHasCorrectType($type, $value)
|
||||||
|
{
|
||||||
if (
|
if (
|
||||||
($type === 'string' && gettype($value) !== 'string') ||
|
($type === 'string' && gettype($value) !== 'string') ||
|
||||||
($type === 'boolean' && !is_bool($value)) ||
|
($type === 'boolean' && !is_bool($value)) ||
|
||||||
($type === 'number' && !is_numeric($value)) ||
|
($type === 'number' && !is_numeric($value)) ||
|
||||||
($type === 'object' && !is_array($value))
|
($type === 'object' && !is_array($value))
|
||||||
) {
|
) {
|
||||||
$this->isConditionCorrect = false;
|
return false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function checkConditions($conditions) {
|
private function checkConditions($conditions)
|
||||||
|
{
|
||||||
if (isset($conditions['operatorIdentifier'])) {
|
if (isset($conditions['operatorIdentifier'])) {
|
||||||
if (($conditions['operatorIdentifier'] !== 'and') && ($conditions['operatorIdentifier'] !== 'or')) {
|
if (($conditions['operatorIdentifier'] !== 'and') && ($conditions['operatorIdentifier'] !== 'or')) {
|
||||||
$this->isConditionCorrect = false;
|
$this->isConditionCorrect = false;
|
||||||
|
@ -463,19 +485,19 @@ class FormPropertyLogicRule implements Rule, DataAwareRule {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function checkActions($conditions) {
|
private function checkActions($conditions)
|
||||||
|
{
|
||||||
if (is_array($conditions) && count($conditions) > 0) {
|
if (is_array($conditions) && count($conditions) > 0) {
|
||||||
foreach($conditions as $val){
|
foreach($conditions as $val){
|
||||||
if (!in_array($val, static::ACTIONS_VALUES) ||
|
if (!in_array($val, static::ACTIONS_VALUES) ||
|
||||||
(in_array($this->field["type"], ['nf-text', 'nf-page-break', 'nf-divider', 'nf-image']) && !in_array($val, ['hide-block'])) ||
|
(in_array($this->field["type"], ['nf-text', 'nf-page-break', 'nf-divider', 'nf-image']) && !in_array($val, ['hide-block'])) ||
|
||||||
(isset($this->field["hidden"]) && $this->field["hidden"] && !in_array($val, ['show-block','require-answer'])) ||
|
(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']))
|
(isset($this->field["required"]) && $this->field["required"] && !in_array($val, ['make-it-optional', 'hide-block']))
|
||||||
) {
|
) {
|
||||||
$this->isActionCorrect = false;
|
$this->isActionCorrect = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -486,7 +508,8 @@ class FormPropertyLogicRule implements Rule, DataAwareRule {
|
||||||
* @param mixed $value
|
* @param mixed $value
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function passes($attribute, $value) {
|
public function passes($attribute, $value)
|
||||||
|
{
|
||||||
$this->setProperty($attribute);
|
$this->setProperty($attribute);
|
||||||
if(isset($value["conditions"])){
|
if(isset($value["conditions"])){
|
||||||
$this->checkConditions($value["conditions"]);
|
$this->checkConditions($value["conditions"]);
|
||||||
|
@ -501,7 +524,8 @@ class FormPropertyLogicRule implements Rule, DataAwareRule {
|
||||||
* Get the validation error message.
|
* Get the validation error message.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function message() {
|
public function message()
|
||||||
|
{
|
||||||
$errorList = [];
|
$errorList = [];
|
||||||
if(!$this->isConditionCorrect){
|
if(!$this->isConditionCorrect){
|
||||||
$errorList[] = "The logic conditions for ".$this->field['name']." are not complete.";
|
$errorList[] = "The logic conditions for ".$this->field['name']." are not complete.";
|
||||||
|
@ -527,7 +551,7 @@ class FormPropertyLogicRule implements Rule, DataAwareRule {
|
||||||
|
|
||||||
private function setProperty(string $attributeKey)
|
private function setProperty(string $attributeKey)
|
||||||
{
|
{
|
||||||
$attributeKey = Str::of($attributeKey)->replace('.logic','')->toString();
|
$attributeKey = Str::of($attributeKey)->replace('.logic', '')->toString();
|
||||||
$this->field = \Arr::get($this->data, $attributeKey);
|
$this->field = \Arr::get($this->data, $attributeKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,13 @@ class FormLogicConditionChecker
|
||||||
}
|
}
|
||||||
|
|
||||||
private function checkListContains ($condition, $fieldValue): bool {
|
private function checkListContains ($condition, $fieldValue): bool {
|
||||||
return ($fieldValue) ? (count(array_intersect($condition['value'], $fieldValue)) === count($condition['value'])) : false;
|
if (is_null($fieldValue)) return false;
|
||||||
|
|
||||||
|
if (is_array($condition['value'])) {
|
||||||
|
return count(array_intersect($condition['value'], $fieldValue)) === count($condition['value']);
|
||||||
|
} else {
|
||||||
|
return in_array($condition['value'], $fieldValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function checkStartsWith ($condition, $fieldValue): bool {
|
private function checkStartsWith ($condition, $fieldValue): bool {
|
||||||
|
|
|
@ -58,7 +58,7 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (['select', 'multi_select'].includes(this.property.type)) {
|
if (['select', 'multi_select'].includes(this.property.type)) {
|
||||||
componentData.multiple = (this.property.type == 'multi_select')
|
componentData.multiple = false;
|
||||||
componentData.options = this.property[this.property.type].options.map(option => {
|
componentData.options = this.property[this.property.type].options.map(option => {
|
||||||
return {
|
return {
|
||||||
name: option.name,
|
name: option.name,
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="flex px-4 py-1">
|
<div class="flex flex-wrap px-4 py-1 -ml-1 -mt-1">
|
||||||
<select-input ref="ruleSelect" v-model="selectedRule" class="flex-grow mr-1"
|
<select-input ref="ruleSelect" v-model="selectedRule" class="flex-grow ml-1 mr-1 mt-1"
|
||||||
wrapper-class="relative" placeholder="Add condition on input field"
|
wrapper-class="relative" placeholder="Add condition on input field"
|
||||||
:options="groupCtrl.rules" margin-bottom=""
|
:options="groupCtrl.rules" margin-bottom=""
|
||||||
emit-key="identifier"
|
emit-key="identifier"
|
||||||
option-key="identifier"
|
option-key="identifier"
|
||||||
name="group-control-slot-rule"
|
name="group-control-slot-rule"
|
||||||
/>
|
/>
|
||||||
<v-button class="ml-1" color="blue" size="small" :disabled="selectedRule === ''" @click="addRule">
|
<v-button class="ml-1 mt-1" color="blue" size="small" :disabled="selectedRule === ''" @click="addRule">
|
||||||
Add Condition
|
Add Condition
|
||||||
</v-button>
|
</v-button>
|
||||||
<v-button class="ml-1" color="green" size="small" @click="groupCtrl.newGroup">
|
<v-button class="ml-1 mt-1" color="green" size="small" @click="groupCtrl.newGroup">
|
||||||
Add Group
|
Add Group
|
||||||
</v-button>
|
</v-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -64,7 +64,13 @@ function checkContains (condition, fieldValue) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkListContains (condition, fieldValue) {
|
function checkListContains (condition, fieldValue) {
|
||||||
return (fieldValue && fieldValue.length > 0) ? condition.value.every(r => fieldValue.includes(r)) : false
|
if (!fieldValue) return false
|
||||||
|
|
||||||
|
if (Array.isArray(condition.value)) {
|
||||||
|
return condition.value.every(r => fieldValue.includes(r))
|
||||||
|
} else {
|
||||||
|
return fieldValue.includes(condition.value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkStartsWith (condition, fieldValue) {
|
function checkStartsWith (condition, fieldValue) {
|
||||||
|
|
|
@ -56,3 +56,63 @@ it('create form with logic', function () {
|
||||||
'message' => 'Form submission saved.'
|
'message' => 'Form submission saved.'
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('create form with multi select logic', function () {
|
||||||
|
$user = $this->actingAsUser();
|
||||||
|
$workspace = $this->createUserWorkspace($user);
|
||||||
|
$form = $this->createForm($user, $workspace, [
|
||||||
|
'properties' => [
|
||||||
|
[
|
||||||
|
'id' => "title",
|
||||||
|
'name' => "Name",
|
||||||
|
'type' => 'title',
|
||||||
|
'hidden' => false,
|
||||||
|
'required' => false,
|
||||||
|
'logic' => [
|
||||||
|
"conditions" => [
|
||||||
|
"operatorIdentifier"=> "and",
|
||||||
|
"children"=> [
|
||||||
|
[
|
||||||
|
"identifier"=> "multi_select",
|
||||||
|
"value"=> [
|
||||||
|
"operator"=> "contains",
|
||||||
|
"property_meta"=> [
|
||||||
|
'id'=> "93ea3198-353f-440b-8dc9-2ac9a7bee124",
|
||||||
|
"type"=> "multi_select",
|
||||||
|
],
|
||||||
|
"value"=> 'One'
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"actions" => ['require-answer']
|
||||||
|
]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
|
||||||
|
$this->getJson(route('forms.show', $form->slug))
|
||||||
|
->assertSuccessful()
|
||||||
|
->assertJson(function (AssertableJson $json) use ($form) {
|
||||||
|
return $json->where('id', $form->id)
|
||||||
|
->where('properties', function($values){
|
||||||
|
return (count($values[0]['logic']) > 0);
|
||||||
|
})
|
||||||
|
->etc();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Should submit form
|
||||||
|
$forData = ['93ea3198-353f-440b-8dc9-2ac9a7bee124' => ["One"]];
|
||||||
|
$this->postJson(route('forms.answer', $form->slug), $forData)
|
||||||
|
->assertStatus(422)
|
||||||
|
->assertJson([
|
||||||
|
'message' => 'The Name field is required.',
|
||||||
|
'errors' => [
|
||||||
|
'title' => [
|
||||||
|
'The Name field is required.',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
Loading…
Reference in New Issue