From d3cbd0a5e062a1f5cd14f4271e2337f57b226ad4 Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Fri, 3 Feb 2017 00:10:14 -0500 Subject: [PATCH] CRM-19943 - New manage tags UI with jstree --- CRM/Admin/Form.php | 2 +- CRM/Admin/Page/AJAX.php | 50 ++++ CRM/Core/BAO/Tag.php | 16 +- CRM/Core/xml/Menu/Tag.xml | 9 +- CRM/Tag/Form/Edit.php | 131 +++++--- CRM/Tag/Page/Tag.php | 202 ++----------- js/Common.js | 7 +- js/crm.ajax.js | 10 +- templates/CRM/Tag/Form/Edit.tpl | 9 +- templates/CRM/Tag/Page/Tag.tpl | 512 ++++++++++++++++++++++++-------- 10 files changed, 583 insertions(+), 365 deletions(-) diff --git a/CRM/Admin/Form.php b/CRM/Admin/Form.php index cc3186887f..8129e3f184 100644 --- a/CRM/Admin/Form.php +++ b/CRM/Admin/Form.php @@ -91,7 +91,7 @@ class CRM_Admin_Form extends CRM_Core_Form { */ public function setDefaultValues() { // Fetch defaults from the db - if (isset($this->_id) && empty($this->_values)) { + if (!empty($this->_id) && empty($this->_values) && CRM_Utils_Rule::positiveInteger($this->_id)) { $this->_values = array(); $params = array('id' => $this->_id); $baoName = $this->_BAOName; diff --git a/CRM/Admin/Page/AJAX.php b/CRM/Admin/Page/AJAX.php index 5740851eaa..f6859ab670 100644 --- a/CRM/Admin/Page/AJAX.php +++ b/CRM/Admin/Page/AJAX.php @@ -373,4 +373,54 @@ LIMIT $limit"; CRM_Utils_JSON::output($result); } + /** + * Outputs one branch in the tag tree + * + * Used by jstree to incrementally load tags + */ + public static function getTagTree() { + $parent = CRM_Utils_Type::escape(CRM_Utils_Array::value('parent_id', $_GET, 0), 'Integer'); + $result = array(); + + $parentClause = $parent ? "AND tag.parent_id = $parent" : 'AND tag.parent_id IS NULL'; + $sql = "SELECT tag.*, child.id AS child, COUNT(et.id) as usages + FROM civicrm_tag tag + LEFT JOIN civicrm_entity_tag et ON et.tag_id = tag.id + LEFT JOIN civicrm_tag child ON child.parent_id = tag.id + WHERE tag.is_tagset <> 1 $parentClause + GROUP BY tag.id + ORDER BY tag.name"; + $dao = CRM_Core_DAO::executeQuery($sql); + while ($dao->fetch()) { + $style = ''; + if ($dao->color) { + $style = "background-color: {$dao->color}; color: " . CRM_Utils_Color::getContrast($dao->color); + } + $result[] = array( + 'id' => $dao->id, + 'text' => $dao->name, + 'icon' => FALSE, + 'li_attr' => array( + 'title' => ((string) $dao->description) . ($dao->is_reserved ? ' (*' . ts('Reserved') . ')' : ''), + 'class' => $dao->is_reserved ? 'is-reserved' : '', + ), + 'a_attr' => array( + 'style' => $style, + 'class' => 'crm-tag-item', + ), + 'children' => (bool) $dao->child, + 'data' => array( + 'description' => (string) $dao->description, + 'is_selectable' => (bool) $dao->is_selectable, + 'is_reserved' => (bool) $dao->is_reserved, + 'used_for' => $dao->used_for ? explode(',', $dao->used_for) : array(), + 'color' => $dao->color ? $dao->color : '#ffffff', + 'usages' => (int) $dao->usages, + ), + ); + } + + CRM_Utils_JSON::output($result); + } + } diff --git a/CRM/Core/BAO/Tag.php b/CRM/Core/BAO/Tag.php index c1b4ae44f4..936998aa99 100644 --- a/CRM/Core/BAO/Tag.php +++ b/CRM/Core/BAO/Tag.php @@ -395,8 +395,8 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag { * (optional) the array that holds all the db ids - we are moving away from this in bao. * signatures * - * @return object - * CRM_Core_DAO_Tag object on success, otherwise null + * @return CRM_Core_DAO_Tag|null + * object on success, otherwise null */ public static function add(&$params, $ids = array()) { $id = CRM_Utils_Array::value('id', $params, CRM_Utils_Array::value('tag', $ids)); @@ -411,6 +411,13 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag { // get parent details $params['used_for'] = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Tag', $params['parent_id'], 'used_for'); } + elseif (isset($params['used_for']) && is_array($params['used_for'])) { + $params['used_for'] = implode(',', $params['used_for']); + } + + if (isset($params['color']) && strtolower($params['color']) === '#ffffff') { + $params['color'] = ''; + } $tag->copyValues($params); $tag->id = $id; @@ -428,10 +435,11 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag { CRM_Utils_Hook::post($hook, 'Tag', $tag->id, $tag); // if we modify parent tag, then we need to update all children - if ($tag->parent_id === 'null') { + $tag->find(TRUE); + if (!$tag->parent_id && $tag->used_for) { CRM_Core_DAO::executeQuery("UPDATE civicrm_tag SET used_for=%1 WHERE parent_id = %2", array( - 1 => array($params['used_for'], 'String'), + 1 => array($tag->used_for, 'String'), 2 => array($tag->id, 'Integer'), ) ); diff --git a/CRM/Core/xml/Menu/Tag.xml b/CRM/Core/xml/Menu/Tag.xml index 104f896806..f83c14622f 100644 --- a/CRM/Core/xml/Menu/Tag.xml +++ b/CRM/Core/xml/Menu/Tag.xml @@ -12,10 +12,15 @@ 25 - civicrm/tag/add + civicrm/tag/edit New Tag - CRM_Tag_Page_Tag + CRM_Tag_Form_Edit action=add administer CiviCRM;manage tags + + civicrm/ajax/tagTree + CRM_Admin_Page_AJAX::getTagTree + administer CiviCRM;manage tags + diff --git a/CRM/Tag/Form/Edit.php b/CRM/Tag/Form/Edit.php index 6f7cc03d22..0919c7f070 100644 --- a/CRM/Tag/Form/Edit.php +++ b/CRM/Tag/Form/Edit.php @@ -44,27 +44,44 @@ class CRM_Tag_Form_Edit extends CRM_Admin_Form { return 'Tag'; } + public function preProcess() { + CRM_Utils_Request::retrieve('id', 'Integer', $this, FALSE); + $this->set('BAOName', 'CRM_Core_BAO_Tag'); + parent::preProcess(); + } + /** * Build the form object. */ public function buildQuickForm() { if ($this->_action == CRM_Core_Action::DELETE) { - if ($this->_id && $tag = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Tag', $this->_id, 'name', 'parent_id')) { - $url = CRM_Utils_System::url('civicrm/tag', "reset=1"); - CRM_Core_Error::statusBounce(ts("This tag cannot be deleted. You must delete all its child tags ('%1', etc) prior to deleting this tag.", array(1 => $tag)), $url); + $url = CRM_Utils_System::url('civicrm/tag'); + if (!$this->_id) { + $this->_id = explode(',', CRM_Utils_Request::retrieve('id', 'String')); } - if ($this->_values['is_reserved'] == 1 && !CRM_Core_Permission::check('administer reserved tags')) { - CRM_Core_Error::statusBounce(ts("You do not have sufficient permission to delete this reserved tag.")); + $this->_id = (array) $this->_id; + if (!$this->_id) { + CRM_Core_Error::statusBounce(ts("Unknown tag."), $url); + } + foreach ($this->_id as $id) { + if (!CRM_Utils_Rule::positiveInteger($id)) { + CRM_Core_Error::statusBounce(ts("Unknown tag."), $url); + } + if ($tag = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Tag', $id, 'name', 'parent_id')) { + CRM_Core_Error::statusBounce(ts("This tag cannot be deleted. You must delete all its child tags ('%1', etc) prior to deleting this tag.", array(1 => $tag)), $url); + } + if (!CRM_Core_Permission::check('administer reserved tags') && CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Tag', $id, 'is_reserved')) { + CRM_Core_Error::statusBounce(ts("You do not have sufficient permission to delete this reserved tag."), $url); + } + } + if (count($this->_id) > 1) { + $this->assign('delName', ts('%1 tags', array(1 => count($this->_id)))); } } else { - $parentId = NULL; - $isTagSetChild = FALSE; - $this->_isTagSet = CRM_Utils_Request::retrieve('tagset', 'Positive', $this); - if (!$this->_isTagSet && - $this->_id && + if (!$this->_isTagSet && $this->_id && CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Tag', $this->_id, 'is_tagset') ) { $this->_isTagSet = TRUE; @@ -72,8 +89,11 @@ class CRM_Tag_Form_Edit extends CRM_Admin_Form { if ($this->_id) { $parentId = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Tag', $this->_id, 'parent_id'); - $isTagSetChild = $parentId ? CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Tag', $parentId, 'is_tagset') : FALSE; } + else { + $parentId = CRM_Utils_Request::retrieve('parent_id', 'Integer', $this); + } + $isTagSetChild = $parentId ? CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Tag', $parentId, 'is_tagset') : FALSE; if (!$this->_isTagSet) { if (!$isTagSetChild) { @@ -109,7 +129,9 @@ class CRM_Tag_Form_Edit extends CRM_Admin_Form { $isReserved = $this->add('checkbox', 'is_reserved', ts('Reserved?')); - $this->addSelect('used_for', array('multiple' => TRUE, 'option_url' => NULL)); + if (!$isTagSetChild) { + $this->addSelect('used_for', array('multiple' => TRUE, 'option_url' => NULL)); + } $adminTagset = TRUE; if (!CRM_Core_Permission::check('administer Tagsets')) { @@ -135,10 +157,17 @@ class CRM_Tag_Form_Edit extends CRM_Admin_Form { */ public function setDefaultValues() { $defaults = parent::setDefaultValues(); - if (empty($this->_id) || !CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Tag', $this->_id, 'color')) { + $cloneFrom = CRM_Utils_Request::retrieve('clone_from', 'Integer'); + if (empty($this->_id) && $cloneFrom) { + $params = array('id' => $cloneFrom); + CRM_Core_BAO_Tag::retrieve($params, $this->_values); + $this->_values['name'] .= ' (' . ts('copy') . ')'; + $defaults = $this->_values; + } + if (empty($defaults['color'])) { $defaults['color'] = '#ffffff'; } - if (empty($this->_id)) { + if (empty($this->_id) && empty($defaults['used_for'])) { $defaults['used_for'] = 'civicrm_contact'; } return $defaults; @@ -148,46 +177,60 @@ class CRM_Tag_Form_Edit extends CRM_Admin_Form { * Process the form submission. */ public function postProcess() { - // store the submitted values in an array - $params = $this->exportValues(); - if ($this->_id) { - $params['id'] = $this->_id; - } - - if ($this->_action == CRM_Core_Action::ADD || - $this->_action == CRM_Core_Action::UPDATE - ) { - $params['used_for'] = implode(",", $params['used_for']); + if ($this->_action == CRM_Core_Action::DELETE) { + $deleted = 0; + $tag = civicrm_api3('tag', 'getsingle', array('id' => $this->_id[0])); + foreach ($this->_id as $id) { + if (CRM_Core_BAO_Tag::del($id)) { + $deleted++; + } + } + if (count($this->_id) == 1 && $deleted == 1) { + if ($tag['is_tagset']) { + CRM_Core_Session::setStatus(ts("The tag set '%1' has been deleted.", array(1 => $tag['name'])), ts('Deleted'), 'success'); + } + else { + CRM_Core_Session::setStatus(ts("The tag '%1' has been deleted.", array(1 => $tag['name'])), ts('Deleted'), 'success'); + } + } + else { + CRM_Core_Session::setStatus(ts("Deleted %1 tags.", array(1 => $deleted)), ts('Deleted'), 'success'); + } } + else { + $params = $this->exportValues(); + if ($this->_id) { + $params['id'] = $this->_id; + } - $params['is_tagset'] = 0; - if ($this->_isTagSet) { - $params['is_tagset'] = 1; - } + if (isset($params['used_for']) && ($this->_action == CRM_Core_Action::ADD || $this->_action == CRM_Core_Action::UPDATE)) { + $params['used_for'] = implode(",", $params['used_for']); + } - if (!isset($params['is_reserved'])) { - $params['is_reserved'] = 0; - } + $params['is_tagset'] = 0; + if ($this->_isTagSet) { + $params['is_tagset'] = 1; + } - if (!isset($params['is_selectable'])) { - $params['is_selectable'] = 0; - } + if (!isset($params['is_reserved'])) { + $params['is_reserved'] = 0; + } - if (strtolower($params['color']) == '#ffffff') { - $params['color'] = 'null'; - } + if (!isset($params['parent_id']) && $this->get('parent_id')) { + $params['parent_id'] = $this->get('parent_id'); + } + if (empty($params['parent_id'])) { + $params['parent_id'] = ''; + } - if ($this->_action == CRM_Core_Action::DELETE) { - if ($this->_id > 0) { - $tag = civicrm_api3('tag', 'getsingle', array('id' => $this->_id)); - CRM_Core_BAO_Tag::del($this->_id); - CRM_Core_Session::setStatus(ts("The tag '%1' has been deleted.", array(1 => $tag['name'])), ts('Deleted'), 'success'); + if (!isset($params['is_selectable'])) { + $params['is_selectable'] = 0; } - } - else { $tag = CRM_Core_BAO_Tag::add($params); CRM_Core_Session::setStatus(ts("The tag '%1' has been saved.", array(1 => $tag->name)), ts('Saved'), 'success'); + $this->ajaxResponse['tag'] = $tag->toArray(); } + CRM_Core_Session::singleton()->pushUserContext(CRM_Utils_System::url('civicrm/tag')); } } diff --git a/CRM/Tag/Page/Tag.php b/CRM/Tag/Page/Tag.php index 5a1c18259a..4259c60cf5 100644 --- a/CRM/Tag/Page/Tag.php +++ b/CRM/Tag/Page/Tag.php @@ -32,187 +32,45 @@ */ /** - * Page for displaying list of categories. + * Page for managing tags. */ -class CRM_Tag_Page_Tag extends CRM_Core_Page_Basic { - - public $useLivePageJS = TRUE; - - /** - * The action links that we need to display for the browse screen. - * - * @var array - */ - static $_links = NULL; - - /** - * Get BAO. - * - * @return string - * Classname of BAO. - */ - public function getBAOName() { - return 'CRM_Core_BAO_Tag'; - } +class CRM_Tag_Page_Tag extends CRM_Core_Page { /** - * Get action Links. - * - * @return array - * (reference) of action links + * Run page */ - public function &links() { - if (!(self::$_links)) { - self::$_links = array( - CRM_Core_Action::UPDATE => array( - 'name' => ts('Edit'), - 'url' => 'civicrm/tag', - 'qs' => 'action=update&id=%%id%%&reset=1', - 'title' => ts('Edit Tag'), - ), - CRM_Core_Action::DELETE => array( - 'name' => ts('Delete'), - 'url' => 'civicrm/tag', - 'qs' => 'action=delete&id=%%id%%', - 'title' => ts('Delete Tag'), - ), - CRM_Core_Action::FOLLOWUP => array( - 'name' => ts('Merge'), - 'class' => 'merge_tag', - 'title' => ts('Merge Tag'), - ), - ); + public function run() { + CRM_Core_Resources::singleton() + ->addScriptFile('civicrm', 'bower_components/jstree/dist/jstree.min.js', 0, 'html-header') + ->addStyleFile('civicrm', 'bower_components/jstree/dist/themes/default/style.min.css'); + + $usedFor = $tagsets = array(); + + $result = civicrm_api3('OptionValue', 'get', array( + 'return' => array("value", "name"), + 'option_group_id' => "tag_used_for", + )); + foreach ($result['values'] as $value) { + $usedFor[$value['value']] = $value['name']; } - return self::$_links; - } - /** - * Get name of edit form. - * - * @return string - * Classname of edit form. - */ - public function editForm() { - return 'CRM_Tag_Form_Edit'; - } - - /** - * Get form name for edit form. - * - * @return string - * name of this page. - */ - public function editName() { - return 'Tag'; - } - - /** - * Get form name for delete form. - * - * @return string - * name of this page. - */ - public function deleteName() { - return 'Tag'; - } - - /** - * Get user context. - * - * @param null $mode - * - * @return string - * user context. - */ - public function userContext($mode = NULL) { - return 'civicrm/tag'; - } - - /** - * Get name of delete form. - * - * @return string - * Classname of delete form. - */ - public function deleteForm() { - return 'CRM_Tag_Form_Edit'; - } - - /** - * Override function browse() - * - * @param null $action - * @param null $sort - */ - public function browse($action = NULL, $sort = NULL) { - $adminTagSet = FALSE; - if (CRM_Core_Permission::check('administer Tagsets')) { - $adminTagSet = TRUE; - } - $this->assign('adminTagSet', $adminTagSet); - - $reservedClause = !CRM_Core_Permission::check('administer reserved tags') ? "AND t1.is_reserved != 1" : ''; - $query = "SELECT t1.name, t1.id -FROM civicrm_tag t1 LEFT JOIN civicrm_tag t2 ON t1.id = t2.parent_id -WHERE t2.id IS NULL {$reservedClause}"; - $tag = CRM_Core_DAO::executeQuery($query); - - $mergeableTags = array(); - while ($tag->fetch()) { - $mergeableTags[$tag->id] = 1; + $result = civicrm_api3('Tag', 'get', array( + 'return' => array("name", "used_for", "description", "created_id.display_name", "created_date", "is_reserved"), + 'is_tagset' => 1, + 'options' => array('limit' => 0), + )); + foreach ($result['values'] as $id => $tagset) { + $used = explode(',', CRM_Utils_Array::value('used_for', $tagset, '')); + $tagset['used_for_label'] = array_values(array_intersect_key($usedFor, array_flip($used))); + $tagset['display_name'] = $tagset['created_id.display_name']; + unset($tagset['created_id.display_name']); + $tagsets[$id] = $tagset; } - $usedFor = CRM_Core_OptionGroup::values('tag_used_for'); - - $query = " SELECT t1.name, t1.id, t2.name as parent, t1.description, t1.used_for, t1.is_tagset as is_tagset, - t1.is_reserved, t1.parent_id, t1.used_for, t1.color, t2.is_tagset as is_tagset_child, t2.parent_id as grandparent_id - FROM civicrm_tag t1 - LEFT JOIN civicrm_tag t2 ON t1.parent_id = t2.id - LEFT JOIN civicrm_tag t3 ON t2.parent_id = t3.id - ORDER BY CONCAT(IFNULL(t3.name, ''), IFNULL(t2.name, ''), t1.name)"; - - $tag = CRM_Core_DAO::executeQuery($query); - $values = array(); - - $action = CRM_Core_Action::UPDATE + CRM_Core_Action::DELETE; - $permission = CRM_Core_Permission::EDIT; - - while ($tag->fetch()) { - $values[$tag->id] = (array) $tag; - - $used = array(); - if ($values[$tag->id]['used_for']) { - $usedArray = explode(",", $values[$tag->id]['used_for']); - foreach ($usedArray as $key => $value) { - $used[$key] = $usedFor[$value]; - } - } - - $values[$tag->id]['used_for'] = implode(", ", $used); - - $newAction = $action; - if ($values[$tag->id]['is_reserved']) { - $newAction = CRM_Core_Action::UPDATE; - } - - if ($values[$tag->id]['is_tagset'] && !CRM_Core_Permission::check('administer Tagsets')) { - $newAction = 0; - } - - if (array_key_exists($tag->id, $mergeableTags)) { - $newAction += CRM_Core_Action::FOLLOWUP; - } - - // populate action links - if ($newAction) { - $this->action($tag, $newAction, $values[$tag->id], self::links(), $permission, TRUE); - } - else { - $values[$tag->id]['action'] = ''; - } - } + $this->assign('usedFor', $usedFor); + $this->assign('tagsets', $tagsets); - $this->assign('rows', $values); + return parent::run(); } } diff --git a/js/Common.js b/js/Common.js index ac8b8768d1..4600589652 100644 --- a/js/Common.js +++ b/js/Common.js @@ -1661,8 +1661,11 @@ if (!CRM.vars) CRM.vars = {}; return input; case 'string': - // convert iso format - return $.datepicker.parseDate('yy-mm-dd', input.substr(0, 10)); + // convert iso format with or without dashes + if (input.indexOf('-') > 0) { + return $.datepicker.parseDate('yy-mm-dd', input.substr(0, 10)); + } + return $.datepicker.parseDate('yymmdd', input.substr(0, 8)); case 'number': // convert unix timestamp diff --git a/js/crm.ajax.js b/js/crm.ajax.js index b01e814bf0..262227ea89 100644 --- a/js/crm.ajax.js +++ b/js/crm.ajax.js @@ -496,7 +496,7 @@ url = $el.attr('href'), popup = $el.data('popup-type') === 'page' ? CRM.loadPage : CRM.loadForm, settings = $el.data('popup-settings') || {}, - formSuccess = false; + formData = false; settings.dialog = settings.dialog || {}; if (e.isDefaultPrevented() || !CRM.config.ajaxPopupsEnabled || !url || $el.is(exclude)) { return; @@ -513,12 +513,12 @@ // Trigger events from the dialog on the original link element $el.trigger('crmPopupOpen', [dialog]); // Listen for success events and buffer them so we only trigger once - dialog.on('crmFormSuccess.crmPopup crmPopupFormSuccess.crmPopup', function() { - formSuccess = true; + dialog.on('crmFormSuccess.crmPopup crmPopupFormSuccess.crmPopup', function(e, data) { + formData = data; }); dialog.on('dialogclose.crmPopup', function(e, data) { - if (formSuccess) { - $el.trigger('crmPopupFormSuccess', [dialog, data]); + if (formData) { + $el.trigger('crmPopupFormSuccess', [dialog, formData]); } $el.trigger('crmPopupClose', [dialog, data]); }); diff --git a/templates/CRM/Tag/Form/Edit.tpl b/templates/CRM/Tag/Form/Edit.tpl index 646dd7c519..0f78e0f839 100644 --- a/templates/CRM/Tag/Form/Edit.tpl +++ b/templates/CRM/Tag/Form/Edit.tpl @@ -42,6 +42,7 @@ {$form.parent_id.html} {/if} + {if $form.used_for} {$form.used_for.label} {$form.used_for.html}
@@ -52,6 +53,7 @@ + {/if} {if $form.color.html} {$form.color.label} @@ -81,7 +83,7 @@
{/if} {else} -
{ts 1=$delName}Are you sure you want to delete %1 Tag?{/ts}
{ts}This tag will be removed from any currently tagged contacts, and users will no longer be able to assign contacts to this tag.{/ts}
+
{ts 1=$delName}Are you sure you want to delete %1?{/ts}
{ts}This tag will be removed from any currently tagged contacts, and users will no longer be able to assign contacts to this tag.{/ts}
{/if}
{include file="CRM/common/formButtons.tpl" location="bottom"}
@@ -90,8 +92,9 @@ CRM.$(function($) { var $form = $('form.{/literal}{$form.formClass}{literal}'); function toggleUsedFor() { - $('.crm-tag-form-block-used_for', $form).toggle(!$(this).val()); - if ($(this).val()) { + var value = $(this).val() && $(this).val() !== '0'; + $('.crm-tag-form-block-used_for', $form).toggle(!value); + if (value) { $('select#used_for', $form).val('').change(); } } diff --git a/templates/CRM/Tag/Page/Tag.tpl b/templates/CRM/Tag/Page/Tag.tpl index dd292d70b9..fd368462c5 100644 --- a/templates/CRM/Tag/Page/Tag.tpl +++ b/templates/CRM/Tag/Page/Tag.tpl @@ -23,139 +23,241 @@ | see the CiviCRM license FAQ at http://civicrm.org/licensing | +--------------------------------------------------------------------+ *} +
+
+ {ts 1=', '|implode:$usedFor}Tags are a convenient way to categorize data (%1).{/ts}
+ {ts}Create predefined tags in the main tree, or click the + to add a set for free tagging.{/ts} + {docURL page="user/organising-your-data/groups-and-tags"} +
-{capture assign=docLink}{docURL page="user/organising-your-data/groups-and-tags"}{/capture} - -{if $action eq 1 or $action eq 2 or $action eq 8} - {include file="CRM/Tag/Form/Edit.tpl"} -{else} -
-
- {ts 1=$docLink}Tags can be assigned to any contact record, and are a convenient way to find contacts. You can create as many tags as needed to organize and segment your records.{/ts} {$docLink} -
- - {if $rows} -
- -
- {if !($action eq 1 and $action eq 2)} -
- -
- {/if} - {strip} - - - - - - - - - - - - - {foreach from=$rows item=row key=id } - {if !$row.is_tagset && !$row.is_tagset_child} - - - - - - - - - - {/if} - {/foreach} -
{ts}Tag{/ts}{ts}ID{/ts}{ts}Description{/ts}{ts}Parent (ID){/ts}{ts}Used For{/ts}{ts}Reserved?{/ts}
- {$row.name} - {$row.id}{$row.description} {$row.parent}{if $row.parent_id} ({$row.parent_id}){/if}{$row.used_for}{if $row.is_reserved}{ts}Reserved{/ts}{/if}{$row.action|replace:'xx':$row.id}
- {/strip} -
-
- {if !($action eq 1 and $action eq 2) && $adminTagSet} -
- -
- {/if} - {strip} - - - - - - - - - - - - - {foreach from=$rows item=row key=id} - {if $row.is_tagset || $row.is_tagset_child} - - - - - - - - - - {/if} - {/foreach} -
{ts}Tag{/ts}{ts}ID{/ts}{ts}Description{/ts}{ts}Parent (ID){/ts}{ts}Used For{/ts}{ts}Reserved?{/ts}
- {$row.name} - {$row.id}{$row.description} {$row.parent}{if $row.parent_id} ({$row.parent_id}){/if}{$row.used_for}{if $row.is_reserved}{ts}Reserved{/ts}{/if}{$row.action|replace:'xx':$row.id}
- {/strip} -
+
+ +
+
+ {ts}Organize the tag hierarchy by clicking and dragging. Shift-click to select multiple tags to merge/move/delete.{/ts}
- {if !($action eq 1 and $action eq 2)} -
- -
- {/if} -
- {include file="CRM/common/jsortable.tpl"} - {else} -
-
  - {capture assign=crmURL}{crmURL p='civicrm/tag' q="action=add&reset=1"}{/capture} - {ts 1=$crmURL}There are no Tags present. You can add one.{/ts} +
+ {foreach from=$tagsets item=set} +
- {/if} - + {/foreach} +
+
- +
+{crmAPI entity="Contact" action="getsingle" var="user" return='display_name' id="user_contact_id"} {literal} - - + })(CRM.$, CRM._); + + {/literal} -{/if} + + + + + + + -- 2.25.1