From 79ae07d987f0adb5a61301f6dce0d303dee6d9d1 Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Wed, 12 Feb 2014 23:06:11 -0800 Subject: [PATCH] CRM-13929 - Develop entityRef create mode --- CRM/Core/BAO/UFGroup.php | 35 +++++++++++++++++++++++++++- CRM/Core/Form.php | 33 ++++++++++++++++++++++---- CRM/Core/Resources.php | 4 ++-- CRM/Profile/Form/Edit.php | 6 +++-- api/v3/Generic/Getlist.php | 3 ++- css/civicrm.css | 25 ++++++++++++++------ js/Common.js | 47 +++++++++++++++++++++++++++++++++++--- 7 files changed, 132 insertions(+), 21 deletions(-) diff --git a/CRM/Core/BAO/UFGroup.php b/CRM/Core/BAO/UFGroup.php index 40fbe5d6eb..635979e3e6 100644 --- a/CRM/Core/BAO/UFGroup.php +++ b/CRM/Core/BAO/UFGroup.php @@ -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 * diff --git a/CRM/Core/Form.php b/CRM/Core/Form.php index d183338798..5bf14d29ff 100644 --- a/CRM/Core/Form.php +++ b/CRM/Core/Form.php @@ -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'); } /** diff --git a/CRM/Core/Resources.php b/CRM/Core/Resources.php index 26bd78fc75..3f76348ad1 100644 --- a/CRM/Core/Resources.php +++ b/CRM/Core/Resources.php @@ -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", diff --git a/CRM/Profile/Form/Edit.php b/CRM/Profile/Form/Edit.php index 0ea8cfc1e7..6921534bd0 100644 --- a/CRM/Profile/Form/Edit.php +++ b/CRM/Profile/Form/Edit.php @@ -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, diff --git a/api/v3/Generic/Getlist.php b/api/v3/Generic/Getlist.php index c3388f9471..12bad54b9f 100644 --- a/api/v3/Generic/Getlist.php +++ b/api/v3/Generic/Getlist.php @@ -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? diff --git a/css/civicrm.css b/css/civicrm.css index e9de3c6930..214fa88c16 100644 --- a/css/civicrm.css +++ b/css/civicrm.css @@ -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; diff --git a/js/Common.js b/js/Common.js index 6ec6e97e1c..ebb90d1bb3 100644 --- a/js/Common.js +++ b/js/Common.js @@ -283,6 +283,18 @@ CRM.validate = CRM.validate || { markup += ''; return markup; }; + + CRM.utils.formatSelect2CreateLinks = function($el) { + var markup = ''; + $.each($el.data('create-links'), function(k, link) { + markup += ' '; + if (link.name) { + markup += ' '; + } + markup += link.label + ''; + }); + return markup; + }; // Initialize widgets $(document).on('crmLoad', function(e) { @@ -308,7 +320,8 @@ CRM.validate = CRM.validate || { $(this).nextUntil('option[value^=crm_optgroup]').wrapAll(''); $(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') + '
' + CRM.utils.formatSelect2CreateLinks($el); + }; + options.formatNoMatches = function() { + return $el.data('select-params').formatNoMatches + '
' + 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'); }); }); -- 2.25.1