CRM-14165 - Add client-side options editor and add to activity form
authorColeman Watts <coleman@civicrm.org>
Tue, 4 Feb 2014 22:26:30 +0000 (14:26 -0800)
committerColeman Watts <coleman@civicrm.org>
Tue, 4 Feb 2014 22:26:30 +0000 (14:26 -0800)
CRM/Activity/Form/Activity.php
CRM/Case/Form/Activity.php
CRM/Core/Form.php
CRM/Core/Form/Renderer.php
js/Common.js
xml/schema/Activity/Activity.xml

index f4b28b9df9ae8d3a44c7b9c7c16be41e29383e95..23af98507ed3ce415865e346a8a9a78b73ca5041 100644 (file)
@@ -159,17 +159,11 @@ class CRM_Activity_Form_Activity extends CRM_Contact_Form_Task {
       ),
       'status_id' => array(
         'type' => 'select',
-        'label' => ts('Status'),
-        'attributes' =>
-        CRM_Core_PseudoConstant::activityStatus(),
-        'required' => TRUE
+        'required' => TRUE,
       ),
       'priority_id' => array(
         'type' => 'select',
-        'label' => ts('Priority'),
-        'attributes' =>
-        CRM_Core_PseudoConstant::get('CRM_Activity_DAO_Activity', 'priority_id'),
-        'required' => TRUE
+        'required' => TRUE,
       ),
       'source_contact_id' => array(
         'type' => 'text',
@@ -694,18 +688,15 @@ class CRM_Activity_Form_Activity extends CRM_Contact_Form_Task {
 
     foreach ($this->_fields as $field => $values) {
       if (!empty($this->_fields[$field])) {
-        $attribute = NULL;
-        if (!empty($values['attributes'])) {
-          $attribute = $values['attributes'];
-        }
+        $attribute = CRM_Utils_Array::value('attributes', $values);
+        $required = !empty($values['required']);
 
-        $required = FALSE;
-        if (!empty($values['required'])) {
-          $required = TRUE;
-        }
         if ($values['type'] == 'wysiwyg') {
           $this->addWysiwyg($field, $values['label'], $attribute, $required);
         }
+        elseif ($values['type'] == 'select' && empty($attribute)) {
+          $this->addSelect('CRM_Activity_BAO_Activity', $field, array(), $required);
+        }
         elseif ($field != 'source_contact_id') {
           $this->add($values['type'], $field, $values['label'], $attribute, $required);
         }
index eb0d6fcc6465a97de5eaf99a6aabafc3d5acf8d6..a6f2f9f04d3e6d2d688d5131d310dc42ffec5d19 100644 (file)
@@ -290,6 +290,8 @@ class CRM_Case_Form_Activity extends CRM_Activity_Form_Activity {
     $this->assign('urlPath', 'civicrm/case/activity');
 
     $encounterMediums = CRM_Case_PseudoConstant::encounterMedium();
+    // Fixme: what's the justification for this? It seems like it is just re-adding an option in case it is the default and disabled.
+    // Is that really a big problem?
     if ($this->_activityTypeFile == 'OpenCase') {
       $this->_encounterMedium = CRM_Core_DAO::getFieldValue('CRM_Activity_DAO_Activity', $this->_activityId,
         'medium_id'
index 8b20d5c652df3684f973c47977f5f7197807ef7e..b6b573f7a3c44e4aed1d8f21636749cd122ad1bd 100644 (file)
@@ -904,6 +904,7 @@ class CRM_Core_Form extends HTML_QuickForm_Page {
   /**
    * Adds a select based on field metadata
    * TODO: This could be even more generic and widget type (select in this case) could also be read from metadata
+   * Perhaps a method like $form->bind($name) which would look up all metadata for named field
    * @param CRM_Core_DAO $baoName - string representing bao object
    * @param $name
    * @param array $props
@@ -922,25 +923,28 @@ class CRM_Core_Form extends HTML_QuickForm_Page {
     if (!empty($props['placeholder']) && empty($props['multiple'])) {
       $options = array('' => '') + $options;
     }
+    $bao = new $baoName;
     // Handle custom field
     if (strpos($name, 'custom_') === 0 && is_numeric($name[7])) {
       list(, $id) = explode('_', $name);
       $label = isset($props['label']) ? $props['label'] : CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomField', 'label', $id);
-      $props['data-option-group'] = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomField', 'option_group_id', $id);
+      $gid = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomField', 'option_group_id', $id);
+      $props['data-option-group-url'] = 'civicrm/admin/options/' . CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionGroup', $gid);
     }
     // Core field
     else {
-      $bao = new $baoName;
       $meta = $bao->getFieldSpec($name);
-      $bao->free();
-      // Todo: localize
-      $label = CRM_Utils_Array::value('label', $props, $meta['title']);
+      $label = isset($props['label']) ? $props['label'] : ts($meta['title']);
       if (!empty($meta['pseudoconstant']['optionGroupName'])) {
-        $props['data-option-group'] = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionGroup', $meta['pseudoconstant']['optionGroupName'], 'id', 'name');
+        $props['data-option-group-url'] = 'civicrm/admin/options/' . $meta['pseudoconstant']['optionGroupName'];
       }
     }
+    require_once 'api/api.php';
+    $props['data-api-entity'] = _civicrm_api_get_entity_name_from_dao($bao);
+    $bao->free();
     $props['class'] = isset($props['class']) ? $props['class'] . ' ' : '';
     $props['class'] .= "crm-select2";
+    CRM_Utils_Array::remove($props, 'label');
     return $this->add('select', $name, $label, $options, $required, $props);
   }
 
index bc15901d886e484f20d6928c3ccdd1a56b784548..0783e4a046227177f29d152f8b8fd99c7da53a8c 100644 (file)
@@ -117,7 +117,7 @@ class CRM_Core_Form_Renderer extends HTML_QuickForm_Renderer_ArraySmarty {
       }
     }
 
-    if ($element->getType() == 'select' && $element->getAttribute('data-option-group')) {
+    if ($element->getType() == 'select' && $element->getAttribute('data-option-group-url')) {
       $this->addOptionsEditLink($el, $element);
     }
 
@@ -216,7 +216,7 @@ class CRM_Core_Form_Renderer extends HTML_QuickForm_Renderer_ArraySmarty {
    */
   function addOptionsEditLink(&$el, $field) {
     if (CRM_Core_Permission::check('administer CiviCRM')) {
-      $el['html'] .= ' &nbsp; <a href="#" class="crm-edit-optionvalue-link" title="' . ts('Edit Options') . '" data-option-group="' . $field->getAttribute('data-option-group') . '"><span class="batch-edit"></span></a>';
+      $el['html'] .= ' &nbsp; <a href="#" class="crm-edit-optionvalue-link" title="' . ts('Edit Options') . '" data-option-group-url="' . $field->getAttribute('data-option-group-url') . '"><span class="batch-edit"></span></a>';
     }
   }
 }
index 37f299e93df3fd27a033b5c017ac8a1a2eed01d3..0fc1c0fc73a96e72eee3a6e96b2ee24846eb247b 100644 (file)
@@ -247,6 +247,7 @@ function showHideRow(index) {
   return false;
 }
 
+CRM.utils = CRM.utils || {};
 CRM.strings = CRM.strings || {};
 CRM.validate = CRM.validate || {
   params: {},
@@ -266,6 +267,28 @@ CRM.validate = CRM.validate || {
     return !!$(e.target).closest('.ui-dialog, .ui-datepicker, .select2-drop').length;
   };
 
+  /**
+   * Populate a select list, overwriting the existing options except for the placeholder.
+   * @param $el jquery collection - 1 or more select elements
+   * @param options array in format returned by api.getoptions
+   */
+  CRM.utils.setOptions = function($el, options) {
+    $el.each(function() {
+      var
+        $elect = $(this),
+        val = $elect.val() || [];
+      if (typeof(val) !== 'array') {
+        val = [val];
+      }
+      $elect.find('option[value!=""]').remove();
+      $.each(options, function(key, option) {
+        var selected = ($.inArray(''+option.key, val) > -1) ? 'selected="selected"' : '';
+        $elect.append('<option value="' + option.key + '"' + selected + '>' + option.value + '</option>');
+      });
+      $elect.trigger('change');
+    });
+  };
+
   // Initialize widgets
   $(document).on('crmLoad', function(e) {
     $('table.row-highlight', e.target)
@@ -907,26 +930,40 @@ CRM.validate = CRM.validate || {
     }
 
     // bind the event for image popup
-    $('body').on('click', 'a.crm-image-popup', function() {
-      var o = $('<div class="crm-container crm-custom-image-popup"><img src=' + $(this).attr('href') + '></div>');
+    $('body')
+      .on('click', 'a.crm-image-popup', function() {
+        var o = $('<div class="crm-container crm-custom-image-popup"><img src=' + $(this).attr('href') + '></div>');
 
-      CRM.confirm('',
-        {
-          title: ts('Preview'),
-          message: o
-        },
-        ts('Done')
-      );
-      return false;
-    });
+        CRM.confirm('',
+          {
+            title: ts('Preview'),
+            message: o
+          },
+          ts('Done')
+        );
+        return false;
+      })
 
+      .on('click', function (event) {
+        $('.btn-slide-active').removeClass('btn-slide-active').find('.panel').hide();
+        if ($(event.target).is('.btn-slide')) {
+          $(event.target).addClass('btn-slide-active').find('.panel').show();
+        }
+      })
+
+      .on('click', 'a.crm-edit-optionvalue-link', function() {
+        var url = $(this).data('option-group-url');
+        CRM.loadForm(CRM.url(url, {reset: 1}))
+          .on('dialogclose', function() {
+            var $elects = $('select[data-option-group-url="' + url + '"]');
+            CRM.api3($elects.data('api-entity'), 'getoptions', {sequential: 1, field: $elects.attr('name')})
+              .done(function(data) {
+                CRM.utils.setOptions($elects, data.values);
+              });
+          });
+        return false;
+      });
     $().crmtooltip();
-    $('body').on('click', function (event) {
-      $('.btn-slide-active').removeClass('btn-slide-active').find('.panel').hide();
-      if ($(event.target).is('.btn-slide')) {
-        $(event.target).addClass('btn-slide-active').find('.panel').show();
-      }
-    });
   });
 
   $.fn.crmAccordions = function (speed) {
index 4f7c55879af59acb7231bd38bbdd1f5aed941840..063b36313a5a0dcd6fed3ae5467e24a714ac4adf 100644 (file)
@@ -60,7 +60,7 @@
   </index>
   <field>
       <name>activity_type_id</name>
-      <title>Activity Type ID</title>
+      <title>Activity Type</title>
       <import>true</import>
       <type>int unsigned</type>
       <required>true</required>
   <field>
       <name>status_id</name>
       <uniqueName>activity_status_id</uniqueName>
-      <title>Activity Status Id</title>
+      <title>Activity Status</title>
       <import>true</import>
       <export>false</export>
       <headerPattern>/(activity.)?status(.label$)?/i</headerPattern>