From ae59375a056e44b358dd0f383bcb73156ef444f1 Mon Sep 17 00:00:00 2001 From: Jaap Jansma <jaap@edeveloper.nl> Date: Thu, 31 May 2018 15:27:34 +0200 Subject: [PATCH] added option group input type --- Civi/FormProcessor/Type/AbstractType.php | 54 +++++++++------ Civi/FormProcessor/Type/Factory.php | 19 ++---- Civi/FormProcessor/Type/OptionGroupType.php | 68 +++++++++++++++++++ ang/form_processor.ang.php | 2 +- ang/form_processor/FormProcessorEditCtrl.js | 3 +- .../DefaultDataInputTable.html | 2 +- .../FormProcessorEditCtrl/InputTable.html | 2 +- .../config/crmFormProcessorSpecification.html | 1 + .../crmFormProcessorTypeConfiguration.html | 35 +++++++++- .../crmFormProcessorTypeConfiguration.js | 1 + .../inputs/InputDialogCtrl.html | 2 +- ang/form_processor/inputs/InputDialogCtrl.js | 4 +- .../inputs/crmFormProcessorInputs.js | 4 +- 13 files changed, 151 insertions(+), 46 deletions(-) create mode 100644 Civi/FormProcessor/Type/OptionGroupType.php diff --git a/Civi/FormProcessor/Type/AbstractType.php b/Civi/FormProcessor/Type/AbstractType.php index 4f06005..bc55a21 100644 --- a/Civi/FormProcessor/Type/AbstractType.php +++ b/Civi/FormProcessor/Type/AbstractType.php @@ -36,16 +36,6 @@ public function __construct($name, $label) { $this->name = $name; $this->label = $label; - - $this->configuration = new ConfigurationBag(); - $this->defaultConfiguration = new ConfigurationBag(); - - foreach($this->getConfigurationSpecification() as $spec) { - if ($spec->getDefaultValue()) { - $this->configuration->set($spec->getName(), $spec->getDefaultValue()); - $this->defaultConfiguration->set($spec->getName(), $spec->getDefaultValue()); - } - } } /** @@ -113,6 +103,21 @@ public function getDefaultConfiguration() { return $this->defaultConfiguration; } + + /** + * Sets the default values of this action + */ + public function setDefaults() { + $this->configuration = new ConfigurationBag(); + $this->defaultConfiguration = new ConfigurationBag(); + + foreach($this->getConfigurationSpecification() as $spec) { + if ($spec->getDefaultValue() !== null) { + $this->configuration->setParameter($spec->getName(), $spec->getDefaultValue()); + $this->defaultConfiguration->setParameter($spec->getName(), $spec->getDefaultValue()); + } + } + } /** * @param ConfigurationBag $configuration @@ -123,17 +128,26 @@ } public function toArray() { - return array( - 'name' => $this->name, - 'label' => $this->label, - 'configuration_spec' => $this->getConfigurationSpecification()->toArray(), - 'configuration' => $this->getConfiguration()->toArray(), - 'default_configuration' => $this->getDefaultConfiguration()->toArray(), - ); + $return['name'] = $this->name; + $return['label'] = $this->label; + $return['configuration_spec'] = $this->getConfigurationSpecification()->toArray(); + $return['default_configuration'] = null; + if ($this->getDefaultConfiguration()) { + $return['default_configuration'] = $this->getDefaultConfiguration()->toArray(); + } + return $return; } - public function jsonSerialize() { - return $this->toArray(); - } + /** + * Returns the data structure to serialize it as a json + */ + public function jsonSerialize() { + $return = $this->toArray(); + // An empty array goes wrong with the default confifuration. + if (empty($return['default_configuration'])) { + $return['default_configuration'] = new \stdClass();; + } + return $return; + } } diff --git a/Civi/FormProcessor/Type/Factory.php b/Civi/FormProcessor/Type/Factory.php index 801942f..cc96080 100644 --- a/Civi/FormProcessor/Type/Factory.php +++ b/Civi/FormProcessor/Type/Factory.php @@ -10,6 +10,7 @@ use \Civi\FormProcessor\Type\AbstractType; use \Civi\FormProcessor\Type\GenericType; use \Civi\FormProcessor\Type\CountryType; + use \Civi\FormProcessor\Type\OptionGroupType; use CRM_FormProcessor_ExtensionUtil as E; @@ -27,6 +28,7 @@ $this->addType(new GenericType('Text', E::ts('Long text'))); $this->addType(new DateType(E::ts('Date'))); $this->addType(new GenericType('Boolean', E::ts('Yes/No'))); + $this->addType(new OptionGroupType('OptionGroup', E::ts('Option Group'))); $this->addType(new CountryType('Country', E::ts('Country'))); } @@ -48,7 +50,9 @@ */ public function getTypeByName($name) { if (isset($this->types[$name])) { - return $this->types[$name]; + $type = clone $this->types[$name]; + $type->setDefaults(); + return $type; } return null; } @@ -60,17 +64,4 @@ return $this->types; } - /** - * Returns an array with the name and label - * - * @return array<string> - */ - public function getTypeLabels() { - $return = array(); - foreach($this->types as $type) { - $return[] = $type->toArray(); - } - return $return; - } - } diff --git a/Civi/FormProcessor/Type/OptionGroupType.php b/Civi/FormProcessor/Type/OptionGroupType.php new file mode 100644 index 0000000..21ed39f --- /dev/null +++ b/Civi/FormProcessor/Type/OptionGroupType.php @@ -0,0 +1,68 @@ +<?php + +/** + * @author Jaap Jansma (CiviCooP) <jaap.jansma@civicoop.org> + * @license http://www.gnu.org/licenses/agpl-3.0.html + */ + +namespace Civi\FormProcessor\Type; + +use \Civi\FormProcessor\Config\Specification; +use \Civi\FormProcessor\Config\SpecificationBag; +use \Civi\FormProcessor\Type\AbstractType; +use \Civi\FormProcessor\Type\OptionListInterface; + +use \CRM_FormProcessor_ExtensionUtil as E; + +class OptionGroupType extends AbstractType implements OptionListInterface { + + /** + * Get the configuration specification + * + * @return SpecificationBag + */ + public function getConfigurationSpecification() { + $optionsGroups = array(); + $optionGroupsApi = civicrm_api3('OptionGroup', 'get', array('is_active' => 1, 'options' => array('limit' => 0))); + foreach($optionGroupsApi['values'] as $optionGroup) { + $optionsGroups[$optionGroup['id']] = $optionGroup['title']; + } + return new SpecificationBag(array( + new Specification('option_group_id', 'Integer', E::ts('Option group'), true, null, null, $optionsGroups, false), + )); + } + + public function validateValue($value) { + if (\CRM_Utils_Type::validate($value, 'String', false) === NULL) { + return false; + } + + $countries = $this->getOptions(); + if (!isset($countries[$value])) { + return false; + } + + return true; + } + + /** + * Returns the type number from CRM_Utils_Type + */ + public function getCrmType() { + return \CRM_Utils_Type::T_STRING; + } + + public function getOptions() { + $option_group_id = $this->configuration->get('option_group_id'); + if (!$option_group_id) { + return array(); + } + $optionsApi = civicrm_api3('OptionValue', 'get', array('option_group_id' => $option_group_id, 'is_active' => 1, 'options' => array('limit' => 0))); + $options = array(); + foreach($optionsApi['values'] as $optionValue) { + $options[$optionValue['value']] = $optionValue['label']; + } + return $options; + } + +} diff --git a/ang/form_processor.ang.php b/ang/form_processor.ang.php index f68b7c5..04981db 100644 --- a/ang/form_processor.ang.php +++ b/ang/form_processor.ang.php @@ -34,7 +34,7 @@ return array ( ), 'settings' => array ( - 'inputTypes' => \Civi::service('form_processor_type_factory')->getTypeLabels(), + 'inputTypes' => \Civi::service('form_processor_type_factory')->getTypes(), 'validators' => \Civi::service('form_processor_validation_factory')->getValidators(), 'outputHandlers' => \Civi::service('form_processor_output_handler_factory')->getHandlersAsArray(), 'defaultOutputHandler' => \Civi::service('form_processor_output_handler_factory')->getDefaultHandler()->toArray(), diff --git a/ang/form_processor/FormProcessorEditCtrl.js b/ang/form_processor/FormProcessorEditCtrl.js index 7ffd51b..7d47497 100644 --- a/ang/form_processor/FormProcessorEditCtrl.js +++ b/ang/form_processor/FormProcessorEditCtrl.js @@ -137,8 +137,7 @@ delete input.id; } var type = angular.copy(input.type); - input.form_processor_instance_id = formProcessor.id; - input.configuration = input.type.configuration; + input.form_processor_instance_id = formProcessor.id; input.type = input.type.name; crmApi(api, 'create', input, true).then(function (input_result){ input.id = input_result['id']; diff --git a/ang/form_processor/FormProcessorEditCtrl/DefaultDataInputTable.html b/ang/form_processor/FormProcessorEditCtrl/DefaultDataInputTable.html index a774062..82b8a3c 100644 --- a/ang/form_processor/FormProcessorEditCtrl/DefaultDataInputTable.html +++ b/ang/form_processor/FormProcessorEditCtrl/DefaultDataInputTable.html @@ -2,6 +2,6 @@ <crm-form-processor-inputs form-processor="formProcessor" inputs="formProcessor.default_data_inputs" - deletedActions="deletedDefaultDataInputs" + deleted-inputs="deletedDefaultDataInputs" entity="FormProcessorDefaultDataInput"> </crm-form-processor-inputs> \ No newline at end of file diff --git a/ang/form_processor/FormProcessorEditCtrl/InputTable.html b/ang/form_processor/FormProcessorEditCtrl/InputTable.html index cbe0cae..71b35d0 100644 --- a/ang/form_processor/FormProcessorEditCtrl/InputTable.html +++ b/ang/form_processor/FormProcessorEditCtrl/InputTable.html @@ -2,6 +2,6 @@ <crm-form-processor-inputs form-processor="formProcessor" inputs="formProcessor.inputs" - deletedActions="deletedInputs" + deleted-inputs="deletedInputs" entity="FormProcessorInput"> </crm-form-processor-inputs> \ No newline at end of file diff --git a/ang/form_processor/config/crmFormProcessorSpecification.html b/ang/form_processor/config/crmFormProcessorSpecification.html index 5defdc2..8c9304b 100644 --- a/ang/form_processor/config/crmFormProcessorSpecification.html +++ b/ang/form_processor/config/crmFormProcessorSpecification.html @@ -13,6 +13,7 @@ </div> <div ng-if="!noLabel" class="clear"></div> </div> + <div ng-if="specification.type == 'fields'"> <div ng-if="!noLabel" class="label"> <label crm-ui-for="specification.name" crm-depth="1" crm-ui-force-required="specification.required">{{specification.title}}</label> diff --git a/ang/form_processor/crmFormProcessorTypeConfiguration.html b/ang/form_processor/crmFormProcessorTypeConfiguration.html index c5512a5..a1e306d 100644 --- a/ang/form_processor/crmFormProcessorTypeConfiguration.html +++ b/ang/form_processor/crmFormProcessorTypeConfiguration.html @@ -1,15 +1,44 @@ <ng-repeat ng-repeat="spec in type.configuration_spec.parameter_specifications"> -<div crm-ui-field="{name: 'spec.name', title: spec.title, required: spec.required}"> + + <div ng-if="spec.options" + crm-ui-field="{name: spec.name, title: spec.title, required: spec.required}"> + <select + style="width: 90%;" + crm-ui-select + crm-ui-id="{{spec.name}}" + ui-options="{allowClear: true}" + name="{{spec.name}}" + ng-model="configuration[spec.name]" + ng-required="spec.required" + > + <option ng-repeat="(key,value) in spec.options" value="{{key}}">{{value}}</option> + </select> + </div> + <div ng-if="spec.fk_entity" + crm-ui-field="{name: spec.name, title: spec.title, required: spec.required}"> + <input + crm-entityref="{entity: spec.fk_entity, select: {allowClear: true, placeholder: spec.title}}" + name="{{spec.name}}" + crm-ui-id="{{spec.name}}" + ng-model="configuration[spec.name]" + ng-required="spec.required" + /> + </div> + +<div ng-if="!spec.options && !spec.fk_entity" + crm-ui-field="{name: spec.name, title: spec.title, required: spec.required}"> <input type="text" name="{{spec.name}}" - ng-model="type.configuration[spec.name]" + crm-ui-id="{{spec.name}}" + ng-model="configuration[spec.name]" class="big crm-form-text" ng-required="spec.required" /> - <div class="description" ng-if="spec.description" ng-bind-html="spec.description"></div> +</div> +<div class="description" ng-if="spec.description" ng-bind-html="spec.description"></div> </ng-repeat> diff --git a/ang/form_processor/crmFormProcessorTypeConfiguration.js b/ang/form_processor/crmFormProcessorTypeConfiguration.js index 8bec3b1..e2b757f 100644 --- a/ang/form_processor/crmFormProcessorTypeConfiguration.js +++ b/ang/form_processor/crmFormProcessorTypeConfiguration.js @@ -5,6 +5,7 @@ restrict: 'E', scope: { type: '=type', + configuration: '=configuration', }, templateUrl: '~/form_processor/crmFormProcessorTypeConfiguration.html', }; diff --git a/ang/form_processor/inputs/InputDialogCtrl.html b/ang/form_processor/inputs/InputDialogCtrl.html index 6da944e..1083a5b 100644 --- a/ang/form_processor/inputs/InputDialogCtrl.html +++ b/ang/form_processor/inputs/InputDialogCtrl.html @@ -38,7 +38,7 @@ </div> <crm-form-processor-type-configuration - type=input.type + type=input.type configuration=input.configuration ></crm-form-processor-type-configuration> <div class="crm-block"> diff --git a/ang/form_processor/inputs/InputDialogCtrl.js b/ang/form_processor/inputs/InputDialogCtrl.js index fbf8206..d69936f 100644 --- a/ang/form_processor/inputs/InputDialogCtrl.js +++ b/ang/form_processor/inputs/InputDialogCtrl.js @@ -11,13 +11,13 @@ $scope.input.deletedValidators = []; } - $scope.$watch('model.input.name', function(newName, oldName) { + $scope.$watch('input.name', function(newName, oldName) { $scope.invalidName = newName && !newName.match(/^[a-z0-9_]+$/) ? true : false; $scope.nameExists = false; if (newName && !$scope.invalidName) { // Check whether the name already exists angular.forEach($scope.model.inputs, function(input, key) { - if (input != $scope.model.input && input.name == newName) { + if (input != $scope.input && input.name == newName) { $scope.nameExists = true; } }); diff --git a/ang/form_processor/inputs/crmFormProcessorInputs.js b/ang/form_processor/inputs/crmFormProcessorInputs.js index 7849be8..569c85b 100644 --- a/ang/form_processor/inputs/crmFormProcessorInputs.js +++ b/ang/form_processor/inputs/crmFormProcessorInputs.js @@ -48,7 +48,8 @@ 'name': '', 'is_required': 0, 'default_value': '', - 'validators': [] + 'validators': [], + 'configuration': angular.copy(inputType.default_configuration), }; $scope.editInput(input); }; @@ -64,6 +65,7 @@ index = $scope.inputs.indexOf(input); var model = { formProcessor: $scope.formProcessor, + inputs: $scope.inputs, input: input, entity: $scope.entity }; -- GitLab