From: Coleman Watts Date: Mon, 24 Oct 2022 21:51:39 +0000 (-0400) Subject: Afform - Use APIv4 autocomplete for all EntityRef fields X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=d02d4bc7042ad703f42f86438318ac3db80fb698;p=civicrm-core.git Afform - Use APIv4 autocomplete for all EntityRef fields --- diff --git a/ang/crmUi.js b/ang/crmUi.js index b9ee8a086e..9a52b9c616 100644 --- a/ang/crmUi.js +++ b/ang/crmUi.js @@ -720,12 +720,15 @@ }, bindToController: { crmAutocomplete: '<', - crmAutocompleteParams: '<' + crmAutocompleteParams: '<', + multiple: '<' }, controller: function($element, $timeout) { var ctrl = this; $timeout(function() { - $element.crmAutocomplete(ctrl.crmAutocomplete, ctrl.crmAutocompleteParams); + $element.crmAutocomplete(ctrl.crmAutocomplete, ctrl.crmAutocompleteParams, { + multiple: ctrl.multiple + }); // Ensure widget is updated when model changes if (ctrl.ngModel) { ctrl.ngModel.$render = function() { diff --git a/ext/afform/admin/Civi/AfformAdmin/AfformAdminMeta.php b/ext/afform/admin/Civi/AfformAdmin/AfformAdminMeta.php index 4b16828c3e..7ed1ca938d 100644 --- a/ext/afform/admin/Civi/AfformAdmin/AfformAdminMeta.php +++ b/ext/afform/admin/Civi/AfformAdmin/AfformAdminMeta.php @@ -127,8 +127,9 @@ class AfformAdminMeta { // Add existing entity field $idField = CoreUtil::getIdFieldName($entityName); $fields[$idField]['readonly'] = FALSE; - $fields[$idField]['input_type'] = 'Existing'; + $fields[$idField]['input_type'] = 'EntityRef'; $fields[$idField]['is_id'] = TRUE; + $fields[$idField]['fk_entity'] = $entityName; $fields[$idField]['label'] = E::ts('Existing %1', [1 => CoreUtil::getInfoItem($entityName, 'title')]); // Mix in alterations declared by afform entities $afEntity = self::getMetadata()['entities'][$entityName] ?? []; diff --git a/ext/afform/admin/ang/afGuiEditor/elements/afGuiField-menu.html b/ext/afform/admin/ang/afGuiEditor/elements/afGuiField-menu.html index b72d473f8b..ecd36dd3d5 100644 --- a/ext/afform/admin/ang/afGuiEditor/elements/afGuiField-menu.html +++ b/ext/afform/admin/ang/afGuiEditor/elements/afGuiField-menu.html @@ -1,4 +1,4 @@ -
  • +
  • -
  • +
  • @@ -18,13 +18,13 @@ {{:: ts('Required') }}
  • -
  • +
  • {{:: ts('Default value') }}
  • -
  • +
  • diff --git a/ext/afform/admin/ang/afGuiEditor/elements/afGuiField.component.js b/ext/afform/admin/ang/afGuiEditor/elements/afGuiField.component.js index 8a3638ae68..86bbc8b9c8 100644 --- a/ext/afform/admin/ang/afGuiEditor/elements/afGuiField.component.js +++ b/ext/afform/admin/ang/afGuiEditor/elements/afGuiField.component.js @@ -51,8 +51,7 @@ }; this.getFkEntity = function() { - var defn = ctrl.getDefn(), - fkEntity = defn.is_id ? ctrl.container.getMainEntityType() : defn.fk_entity; + var fkEntity = ctrl.getDefn().fk_entity; return ctrl.editor.meta.entities[fkEntity]; }; diff --git a/ext/afform/admin/ang/afGuiEditor/inputType/Existing.html b/ext/afform/admin/ang/afGuiEditor/inputType/Existing.html deleted file mode 100644 index d2538363fd..0000000000 --- a/ext/afform/admin/ang/afGuiEditor/inputType/Existing.html +++ /dev/null @@ -1,8 +0,0 @@ -
    -
    - -
    - -
    -
    -
    diff --git a/ext/afform/core/Civi/Afform/AfformMetadataInjector.php b/ext/afform/core/Civi/Afform/AfformMetadataInjector.php index 5810e62a17..a994be24a3 100644 --- a/ext/afform/core/Civi/Afform/AfformMetadataInjector.php +++ b/ext/afform/core/Civi/Afform/AfformMetadataInjector.php @@ -124,7 +124,7 @@ class AfformMetadataInjector { if ($inputType === 'Select' || $inputType === 'ChainSelect') { $fieldInfo['input_attrs']['placeholder'] = E::ts('Select'); } - elseif ($inputType === 'EntityRef') { + elseif ($inputType === 'EntityRef' && empty($field['is_id'])) { $info = civicrm_api4('Entity', 'get', [ 'where' => [['name', '=', $fieldInfo['fk_entity']]], 'checkPermissions' => FALSE, diff --git a/ext/afform/core/Civi/Afform/FormDataModel.php b/ext/afform/core/Civi/Afform/FormDataModel.php index 18cc358689..646f2641f5 100644 --- a/ext/afform/core/Civi/Afform/FormDataModel.php +++ b/ext/afform/core/Civi/Afform/FormDataModel.php @@ -231,8 +231,9 @@ class FormDataModel { // Id field for selecting existing entity if ($action === 'create' && $field['name'] === CoreUtil::getIdFieldName($entityName)) { $entityTitle = CoreUtil::getInfoItem($entityName, 'title'); - $field['input_type'] = 'Existing'; - $field['entity'] = $entityName; + $field['input_type'] = 'EntityRef'; + $field['fk_entity'] = $entityName; + $field['is_id'] = TRUE; $field['label'] = E::ts('Existing %1', [1 => $entityTitle]); $field['input_attrs']['placeholder'] = E::ts('Select %1', [1 => $entityTitle]); } diff --git a/ext/afform/core/Civi/Api4/Subscriber/AutocompleteSubscriber.php b/ext/afform/core/Civi/Api4/Subscriber/AutocompleteSubscriber.php index 685a99c95d..d288a99c6f 100644 --- a/ext/afform/core/Civi/Api4/Subscriber/AutocompleteSubscriber.php +++ b/ext/afform/core/Civi/Api4/Subscriber/AutocompleteSubscriber.php @@ -14,6 +14,7 @@ namespace Civi\Api4\Subscriber; use Civi\Afform\FormDataModel; use Civi\API\Events; use Civi\Api4\Afform; +use Civi\Api4\Utils\CoreUtil; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** @@ -52,20 +53,25 @@ class AutocompleteSubscriber implements EventSubscriberInterface { } $formDataModel = new FormDataModel($afform['layout']); $entity = $formDataModel->getEntity($entityName); + $isId = $fieldName === CoreUtil::getIdFieldName($entity['type']); + // For the "Existing Entity" selector, // Look up the "type" fields (e.g. contact_type, activity_type_id, case_type_id, etc) - $typeFields = []; - if ($entity['type'] === 'Contact') { - $typeFields = ['contact_type', 'contact_sub_type']; - } - else { - $extends = array_column(\CRM_Core_BAO_CustomGroup::getCustomGroupExtendsOptions(), 'grouping', 'id'); - $typeFields = (array) ($extends[$entity['type']] ?? NULL); - } - // If entity has a type set in the values, auto-apply that to filters - foreach ($typeFields as $typeField) { - if (!empty($entity['data'][$typeField])) { - $apiRequest->addFilter($typeField, $entity['data'][$typeField]); + // And apply it as a filter if specified on the form. + if ($isId) { + $typeFields = []; + if ($entity['type'] === 'Contact') { + $typeFields = ['contact_type', 'contact_sub_type']; + } + else { + $extends = array_column(\CRM_Core_BAO_CustomGroup::getCustomGroupExtendsOptions(), 'grouping', 'id'); + $typeFields = (array) ($extends[$entity['type']] ?? NULL); + } + // If entity has a type set in the values, auto-apply that to filters + foreach ($typeFields as $typeField) { + if (!empty($entity['data'][$typeField])) { + $apiRequest->addFilter($typeField, $entity['data'][$typeField]); + } } } diff --git a/ext/afform/core/ang/af/afField.component.js b/ext/afform/core/ang/af/afField.component.js index 78a5ba0403..6bdece3888 100644 --- a/ext/afform/core/ang/af/afField.component.js +++ b/ext/afform/core/ang/af/afField.component.js @@ -173,12 +173,25 @@ } }; + ctrl.isReadonly = function() { + if (ctrl.defn.is_id) { + return ctrl.afFieldset.getEntity().actions.update === false; + } + // TODO: Not actually used, but could be used if we wanted to render displayOnly + // fields as more than just raw data. I think we probably ought to do so for entityRef fields + // Since the ids are kind of meaningless. Making that change would require adding a function + // to get the widget template rather than just concatenating the input_type into an ngInclude. + return ctrl.defn.input_type === 'DisplayOnly'; + }; + // ngChange callback from Existing entity field - ctrl.onSelectExisting = function() { - var val = $scope.getSetSelect(); - var entity = ctrl.afFieldset.modelName; - var index = ctrl.getEntityIndex(); - ctrl.afFieldset.afFormCtrl.loadData(entity, index, val); + ctrl.onSelectEntity = function() { + if (ctrl.defn.is_id) { + var val = $scope.getSetSelect(); + var entity = ctrl.afFieldset.modelName; + var index = ctrl.getEntityIndex(); + ctrl.afFieldset.afFormCtrl.loadData(entity, index, val); + } }; // Params for the Afform.submitFile API when uploading a file field diff --git a/ext/afform/core/ang/af/fields/EntityRef.html b/ext/afform/core/ang/af/fields/EntityRef.html index 70cb8d2284..e10509cdc5 100644 --- a/ext/afform/core/ang/af/fields/EntityRef.html +++ b/ext/afform/core/ang/af/fields/EntityRef.html @@ -1 +1,11 @@ - + diff --git a/ext/afform/core/ang/af/fields/Existing.html b/ext/afform/core/ang/af/fields/Existing.html deleted file mode 100644 index 7824c6dfdc..0000000000 --- a/ext/afform/core/ang/af/fields/Existing.html +++ /dev/null @@ -1,9 +0,0 @@ - diff --git a/ext/afform/core/tests/phpunit/Civi/Afform/AfformMetadataTest.php b/ext/afform/core/tests/phpunit/Civi/Afform/AfformMetadataTest.php index 5dfc62e1bc..607ee3851a 100644 --- a/ext/afform/core/tests/phpunit/Civi/Afform/AfformMetadataTest.php +++ b/ext/afform/core/tests/phpunit/Civi/Afform/AfformMetadataTest.php @@ -29,7 +29,7 @@ class AfformMetadataTest extends \PHPUnit\Framework\TestCase implements Headless // Ensure the "Existing" contact field exists $this->assertEquals('Existing Contact', $individualFields['id']['label']); - $this->assertEquals('Existing', $individualFields['id']['input_type']); + $this->assertEquals('EntityRef', $individualFields['id']['input_type']); } }