CRM-13929 - Develop entityRef create mode
authorColeman Watts <coleman@civicrm.org>
Thu, 13 Feb 2014 07:06:11 +0000 (23:06 -0800)
committerColeman Watts <coleman@civicrm.org>
Thu, 13 Feb 2014 07:06:11 +0000 (23:06 -0800)
CRM/Core/BAO/UFGroup.php
CRM/Core/Form.php
CRM/Core/Resources.php
CRM/Profile/Form/Edit.php
api/v3/Generic/Getlist.php
css/civicrm.css
js/Common.js

index 40fbe5d6eb3912af309ca45c0a03f2b4afe178e7..635979e3e631dcc6d1f3123a604b19a553deb86b 100644 (file)
@@ -3221,7 +3221,6 @@ AND    ( entity_id IS NULL OR entity_id <= 0 )
     $reservedProfiles = array();
     $profileNames = array();
     if ($type == 'Contact') {
-      $whereClause = 'name IN ( "new_individual", "new_organization", "new_household" )';
       if (CRM_Contact_BAO_ContactType::isActive('Individual')) {
         $profileNames[] = '"new_individual"';
       }
@@ -3252,6 +3251,40 @@ AND    ( entity_id IS NULL OR entity_id <= 0 )
     return $reservedProfiles;
   }
 
+  /**
+   * @param array|string $profiles - name of profile(s) to create links for
+   * @param array $appendProfiles - name of profile(s) to append to each link
+   */
+  static function getCreateLinks($profiles, $appendProfiles = array()) {
+    $profiles = (array) $profiles;
+    $toGet = array_merge($profiles, $appendProfiles);
+    $retrieved = civicrm_api3('uf_group', 'get', array(
+      'name' => array('IN' => $toGet),
+      'is_active' => 1,
+    ));
+    $links = $append = array();
+    if (!empty($retrieved['values'])) {
+      foreach($retrieved['values'] as $id => $profile) {
+        if (in_array($profile['name'], $profiles)) {
+          $links[] = array(
+            'label' => $profile['title'],
+            'url' => CRM_Utils_System::url('civicrm/profile/create', 'reset=1&gid=' . $id),
+            'name' => $profile['name'],
+          );
+        }
+        else {
+          $append[] = $id;
+        }
+      }
+      foreach ($append as $id) {
+        foreach ($links as &$link) {
+          $link['url'] .= ",$id";
+        }
+      }
+    }
+    return $links;
+  }
+
   /**
    * Function to retrieve groups of  profiles
    *
index d1833387985c945a38c2a79923273ecdea8f0db7..5bf14d29ff1ac090a84dd0789540749d89528b93 100644 (file)
@@ -1257,11 +1257,16 @@ class CRM_Core_Form extends HTML_QuickForm_Page {
    * @param array $props mix of html and widget properties, including:
    *  - select - params to give to select2 widget
    *  - entity - defaults to contact
+   *  - create - can the user create a new entity on-the-fly?
+   *             Set to TRUE if entity is contact and you want the default profiles,
+   *             or pass in your own set of links. See output of CRM_Core_BAO_UFGroup::getCreateLinks for format
    *  - api - array of settings for the getlist api
    *  - placeholder - string
    *  - multiple - bool
    *  - class, etc. - other html properties
    * @param bool $required
+   *
+   * @access public
    * @return HTML_QuickForm_Element
    */
   function addEntityRef($name, $label, $props = array(), $required = FALSE) {
@@ -1272,15 +1277,30 @@ class CRM_Core_Form extends HTML_QuickForm_Page {
     $props['class'] = isset($props['class']) ? $props['class'] . ' ' : '';
     $props['class'] .= "crm-select2 crm-form-entityref";
 
-    $props['select'] = CRM_Utils_Array::value('select', $props, array()) + array(
+    if ($props['entity'] == 'contact' && isset($props['create']) && !(CRM_Core_Permission::check('edit all contacts') || CRM_Core_Permission::check('add contacts'))) {
+      unset($props['create']);
+    }
+    if ($props['entity'] == 'contact' && isset($props['create']) && $props['create'] === TRUE) {
+      if (empty($props['api']['params']['contact_type'])) {
+        $props['create'] = CRM_Core_BAO_UFGroup::getCreateLinks(array('new_individual', 'new_organization', 'new_household'));
+      }
+      else {
+        $props['create'] = CRM_Core_BAO_UFGroup::getCreateLinks('new_' . strtolower($props['api']['params']['contact_type']));
+      }
+    }
+
+    $defaults = array(
       'minimumInputLength' => 1,
       'multiple' => !empty($props['multiple']),
       'placeholder' => CRM_Utils_Array::value('placeholder', $props, $required ? ts('- select -') : ts('- none -')),
       'allowClear' => !$required,
-      // Disabled pending https://github.com/ivaynberg/select2/pull/2092
-      //'formatInputTooShort' => ts('Start typing a name or email address...'),
-      //'formatNoMatches' => ts('No contacts found.'),
+      'formatInputTooShort' => ts('Start typing a name...'),
+      'formatNoMatches' => ts('None found.'),
     );
+    if ($props['entity'] == 'contact' && CRM_Core_Config::singleton()->includeEmailInName) {
+      $defaults['formatInputTooShort'] = ts('Start typing a name or email...');
+    }
+    $props['select'] = CRM_Utils_Array::value('select', $props, array()) + $defaults;
 
     $this->entityReferenceFields[] = $name;
     $this->formatReferenceFieldAttributes($props);
@@ -1294,7 +1314,10 @@ class CRM_Core_Form extends HTML_QuickForm_Page {
     $props['data-select-params'] = json_encode($props['select']);
     $props['data-api-params'] = $props['api'] ? json_encode($props['api']) : NULL;
     $props['data-api-entity'] = $props['entity'];
-    CRM_Utils_Array::remove($props, 'multiple', 'select', 'api', 'entity', 'placeholder');
+    if (!empty($props['create'])) {
+      $props['data-create-links'] = json_encode($props['create']);
+    }
+    CRM_Utils_Array::remove($props, 'multiple', 'select', 'api', 'entity', 'placeholder', 'create');
   }
 
   /**
index 26bd78fc75c562db662919fef5ad96a3a5153fa2..3f76348ad1396ef345db1e0f4ef2e9fb802ff481 100644 (file)
@@ -537,8 +537,8 @@ class CRM_Core_Resources {
       "packages/jquery/jquery-migrate-1.2.1.js",
       "packages/jquery/jquery-ui/js/jquery-ui-1.10.3.custom$min.js",
       "packages/jquery/jquery-ui/css/black-tie/jquery-ui-1.10.3.custom$min.css",
-        
-      "packages/jquery/plugins/select2/select2$min.js",
+
+      "packages/jquery/plugins/select2/select2.js", // No mini until release of select2 3.4.6
       "packages/jquery/plugins/select2/select2.css",
 
       "packages/jquery/plugins/jquery.autocomplete.js",
index 0ea8cfc1e723c91754dcea7c578318c1f1874441..6921534bd058511a10a0448c3764700ec43b1268 100644 (file)
@@ -305,6 +305,10 @@ SELECT module
   public function postProcess() {
     parent::postProcess();
 
+    $displayName = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $this->_id, 'display_name');
+    $sortName = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $this->_id, 'sort_name');
+    $this->ajaxResponse['label'] = $sortName;
+
     // this is special case when we create contact using Dialog box
     if ($this->_context == 'dialog') {
       //replace the session stack for redirecting user to contact summary if new contact is created.
@@ -312,8 +316,6 @@ SELECT module
       $session = CRM_Core_Session::singleton();
       $session->replaceUserContext($contactViewURL);
 
-      $displayName = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $this->_id, 'display_name');
-      $sortName = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $this->_id, 'sort_name');
       $returnArray = array(
         'contactID' => $this->_id,
         'displayName' => $displayName,
index c3388f94717323c83d4dd5d23bcf9a58617bec79..12bad54b9f5499e7f0a530ee26b1dac4b19a73a4 100644 (file)
@@ -41,7 +41,8 @@ function civicrm_api3_generic_getList($apiRequest) {
   $fnName = "_civicrm_api3_{$entity}_getlist_params";
   $fnName = function_exists($fnName) ? $fnName : '_civicrm_api3_generic_getlist_params';
   $fnName($request);
-  
+
+  $request['params']['check_permissions'] = !empty($apiRequest['params']['check_permissions']);
   $result = civicrm_api3($entity, 'get', $request['params']);
 
   // Hey api, would you like to format the output?
index e9de3c693085f88e5b1a446ecd63199ee495f6d5..214fa88c16c7d2e1cc179384fb6bc37de8f8aa29 100644 (file)
@@ -2458,7 +2458,7 @@ div.grippie {
   background-image: url("../i/icons/jquery-ui-8A1F11.png")}
 
 .crm-container .edit-icon {
-  background-position: -66px -114px;
+  background-position: -64px -114px;
 }
 .crm-container .previous-icon {
   background-position: -82px -161px;
@@ -2502,10 +2502,16 @@ div.grippie {
   background-position: -194px -129px;
 }
 
+.crm-container .new_individual-icon,
 .crm-container .user-record-icon {
-  background-position: -145px -98px;
+  background-position: -144px -96px;
+}
+.crm-container .new_household-icon {
+  background-position: 0 -112px;
+}
+.crm-container .new_organization-icon {
+  background-position: -112px -112px;
 }
-
 .crm-container .inform-icon {
   background-position: -16px -144px;
   margin-right: 5px;
@@ -2545,7 +2551,7 @@ div.grippie {
   background-position: -3px -161px;
 }
 .crm-container .close-icon {
-  background-position: -82px -130px;
+  background-position: -80px -128px;
 }
 .crm-container .swap-icon {
   background-position: -82px -81px;
@@ -2618,16 +2624,20 @@ div.grippie {
 }
 
 /* Icon hover-buttons */
-.crm-container .crm-hover-button {
+.crm-container a.crm-hover-button {
   display: inline-block;
   border: 1px solid transparent;
+  text-decoration: none;
+  font-size: .8em;
+  color: #000;
+  padding: 1px 2px;
   opacity: .7;
 }
 .crm-container .crm-accordion-header a.crm-hover-button {
   opacity: 1;
 }
-.crm-container .crm-hover-button:hover,
-.crm-container .crm-hover-button:active {
+.crm-container a.crm-hover-button:hover,
+.crm-container a.crm-hover-button:active {
   background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eee), color-stop(1, #ccc));
   background-image: -webkit-linear-gradient(center bottom, #eee 0%, #ccc 100%);
   background-image: -moz-linear-gradient(center bottom, #eee 0%, #ccc 100%);
@@ -2636,6 +2646,7 @@ div.grippie {
   border: 1px solid #AAAAAA;
   border-radius: 4px;
   opacity: 1;
+  color: #2786C2;
 }
 .crm-container .crm-hover-button .icon {
   margin-left: 3px;
index 6ec6e97e1c408b61d47a83e3109df6bc3b41ea31..ebb90d1bb3adeb694c15bbdc0e3217479a0dad91 100644 (file)
@@ -283,6 +283,18 @@ CRM.validate = CRM.validate || {
     markup += '</td></tr></table>';
     return markup;
   };
+  
+  CRM.utils.formatSelect2CreateLinks = function($el) {
+    var markup = '';
+    $.each($el.data('create-links'), function(k, link) {
+      markup += ' <a class="crm-add-entity crm-hover-button" href="' + link.url + '">';
+      if (link.name) {
+        markup += '<span class="icon ' + link.name + '-icon"></span> ';
+      }
+      markup += link.label + '</a>';
+    });
+    return markup;
+  };
 
   // Initialize widgets
   $(document).on('crmLoad', function(e) {
@@ -308,7 +320,8 @@ CRM.validate = CRM.validate || {
         $(this).nextUntil('option[value^=crm_optgroup]').wrapAll('<optgroup label="' + $(this).text() + '" />');
         $(this).remove();
       });
-      var options = $el.data('select-params') || {};
+      // Get a copy of the data rather than a reference
+      var options = $.extend({}, $el.data('select-params') || {});
       // Set placeholder from markup if not specified
       if ($el.is('select:not([multiple])')) {
         options.allowClear = options.allowClear !== undefined ? options.allowClear : !($el.hasClass('required'));
@@ -319,7 +332,8 @@ CRM.validate = CRM.validate || {
       // Autocomplete using the getlist api
       if ($el.data('api-entity') && $el.hasClass('crm-form-entityref')) {
         $el.addClass('crm-ajax-select');
-        $.extend(options, {
+        var settings = {
+          // Use select2 ajax helper instead of CRM.api because it provides more value
           ajax: {
             url: CRM.url('civicrm/ajax/rest'),
             data: function (input, page_num) {
@@ -344,8 +358,35 @@ CRM.validate = CRM.validate || {
           initSelection: function(el, callback) {
             callback(el.data('entity-value'));
           }
-        });
+        };
+        if ($el.data('create-links')) {
+          options.formatInputTooShort = function() {
+            return $el.data('select-params').formatInputTooShort + ' ' + ts('or') + '<br />' + CRM.utils.formatSelect2CreateLinks($el);
+          };
+          options.formatNoMatches = function() {
+            return $el.data('select-params').formatNoMatches + '<br />' + CRM.utils.formatSelect2CreateLinks($el);
+          };
+          $el.on('select2-open', function() {
+            var $el = $(this);
+            $('#select2-drop').off('.crmEntity').on('click.crmEntity', 'a.crm-add-entity', function(e) {
+              $el.select2('close');
+              CRM.loadForm($(this).attr('href'), {
+                dialog: {width: 500, height: 'auto'}
+              }).on('crmFormSuccess', function(e, data) {
+                if ($el.select2('container').hasClass('select2-container-multi')) {
+                  var selection = $el.select2('data').push(data);
+                  $el.select2('data', selection);
+                } else {
+                  $el.select2('data', data);
+                }
+              });
+              return false;
+            });
+          });
+        }
+        options = $.extend(settings, options);
       }
+      options.dropdownCssClass = 'crm-container';
       $(this).select2(options).removeClass('crm-select2');
     });
   });