$result = [];
$whereClauses = ['is_tagset <> 1'];
- $orderColumn = 'name';
+ $orderColumn = 'label';
// fetch all child tags in Array('parent_tag' => array('child_tag_1', 'child_tag_2', ...)) format
$childTagIDs = CRM_Core_BAO_Tag::getChildTags($substring);
$whereClauses[] = "parent_id = $parent";
}
elseif ($substring) {
- $whereClauses['substring'] = " name LIKE '%$substring%' ";
+ $whereClauses['substring'] = " label LIKE '%$substring%' ";
if (!empty($parentIDs)) {
$whereClauses['substring'] = sprintf(" %s OR id IN (%s) ", $whereClauses['substring'], implode(',', $parentIDs));
}
$usedFor = (array) explode(',', $dao->used_for);
$tag = [
'id' => $dao->id,
- 'text' => $dao->name,
+ 'text' => $dao->label,
'a_attr' => [
'class' => 'crm-tag-item',
],
public static function getContactTags($contactID, $count = FALSE) {
$contactTags = [];
if (!$count) {
- $select = "SELECT ct.id, ct.name ";
+ $select = "SELECT ct.id, ct.label ";
}
else {
$select = "SELECT count(*) as cnt";
}
while ($dao->fetch()) {
- $contactTags[$dao->id] = $dao->name;
+ $contactTags[$dao->id] = $dao->label;
}
return $contactTags;
'sort' => "name ASC",
],
'is_tagset' => 0,
- 'return' => ['name', 'description', 'parent_id', 'color', 'is_selectable', 'used_for'],
+ 'return' => ['label', 'description', 'parent_id', 'color', 'is_selectable', 'used_for'],
];
if ($usedFor) {
$params['used_for'] = ['LIKE' => "%$usedFor%"];
$allTags = [];
foreach (CRM_Utils_Array::value('values', civicrm_api3('Tag', 'get', $params)) as $id => $tag) {
$allTags[$id] = [
- 'text' => $tag['name'],
+ 'text' => $tag['label'],
'id' => $id,
'description' => $tag['description'] ?? NULL,
'parent_id' => $tag['parent_id'] ?? NULL,
*/
public static function add(&$params, $ids = []) {
$id = $params['id'] ?? $ids['tag'] ?? NULL;
- if (!$id && !self::dataExists($params)) {
- return NULL;
+ if (!$id) {
+ // Make label from name if missing.
+ if (CRM_Utils_System::isNull($params['label'] ?? NULL)) {
+ // If name is also missing, cannot create object.
+ if (CRM_Utils_System::isNull($params['name'] ?? NULL)) {
+ // FIXME: Throw exception
+ return NULL;
+ }
+ $params['label'] = $params['name'];
+ }
}
// Check permission to create or modify reserved tag
// save creator id and time
if (!$id) {
$params['created_id'] = $params['created_id'] ?? CRM_Core_Session::getLoggedInContactID();
- $params['created_date'] = $params['created_date'] ?? date('YmdHis');
}
$tag = self::writeRecord($params);
return $tag;
}
- /**
- * Check if there is data to create the object.
- *
- * @param array $params
- *
- * @return bool
- */
- public static function dataExists($params) {
- // Disallow empty values except for the number zero.
- // TODO: create a utility for this since it's needed in many places
- if (!empty($params['name']) || (string) $params['name'] === '0') {
- return TRUE;
- }
-
- return FALSE;
- }
-
/**
* Get the tag sets for a entity object.
*
*/
public static function getTagSet($entityTable) {
$tagSets = [];
- $query = "SELECT name, id FROM civicrm_tag
+ $query = "SELECT label, id FROM civicrm_tag
WHERE is_tagset=1 AND parent_id IS NULL and used_for LIKE %1";
$dao = CRM_Core_DAO::executeQuery($query, [
1 => [
],
], TRUE, NULL, FALSE, FALSE);
while ($dao->fetch()) {
- $tagSets[$dao->id] = $dao->name;
+ $tagSets[$dao->id] = $dao->label;
}
return $tagSets;
}
*
* Generated from xml/schema/CRM/Core/EntityTag.xml
* DO NOT EDIT. Generated by CRM_Core_CodeGen
- * (GenCodeChecksum:2fccc138a26fe391325fd641c891cd91)
+ * (GenCodeChecksum:5bca5ff1c4ba7d85034410408464f0ac)
*/
/**
'pseudoconstant' => [
'table' => 'civicrm_tag',
'keyColumn' => 'id',
- 'labelColumn' => 'name',
+ 'labelColumn' => 'label',
+ 'nameColumn' => 'name',
'condition' => 'is_tagset != 1',
],
'add' => '1.1',
*
* Generated from xml/schema/CRM/Core/Tag.xml
* DO NOT EDIT. Generated by CRM_Core_CodeGen
- * (GenCodeChecksum:f8d8698f48fbd60b8d8e0bf8eff40c47)
+ * (GenCodeChecksum:ded9d6a9f9c08146a0205da83c838c91)
*/
/**
*
* @var string
*/
- public static $_labelField = 'name';
+ public static $_labelField = 'label';
/**
* Should CiviCRM log any modifications to this table in the civicrm_log table.
public $id;
/**
- * Name of Tag.
+ * Unique machine name
*
* @var string
* (SQL type: varchar(64))
*/
public $name;
+ /**
+ * User-facing tag name
+ *
+ * @var string
+ * (SQL type: varchar(64))
+ * Note that values will be retrieved from the database as a string.
+ */
+ public $label;
+
/**
* Optional verbose description of the tag.
*
'name' => 'name',
'type' => CRM_Utils_Type::T_STRING,
'title' => ts('Tag Name'),
- 'description' => ts('Name of Tag.'),
+ 'description' => ts('Unique machine name'),
'required' => TRUE,
'maxlength' => 64,
'size' => CRM_Utils_Type::BIG,
'localizable' => 0,
'add' => '1.1',
],
+ 'label' => [
+ 'name' => 'label',
+ 'type' => CRM_Utils_Type::T_STRING,
+ 'title' => ts('Tag Label'),
+ 'description' => ts('User-facing tag name'),
+ 'required' => TRUE,
+ 'maxlength' => 64,
+ 'size' => CRM_Utils_Type::BIG,
+ 'usage' => [
+ 'import' => FALSE,
+ 'export' => FALSE,
+ 'duplicate_matching' => FALSE,
+ 'token' => FALSE,
+ ],
+ 'where' => 'civicrm_tag.label',
+ 'table_name' => 'civicrm_tag',
+ 'entity' => 'Tag',
+ 'bao' => 'CRM_Core_BAO_Tag',
+ 'localizable' => 0,
+ 'html' => [
+ 'type' => 'Text',
+ ],
+ 'add' => '5.68',
+ ],
'description' => [
'name' => 'description',
'type' => CRM_Utils_Type::T_STRING,
'pseudoconstant' => [
'table' => 'civicrm_tag',
'keyColumn' => 'id',
- 'labelColumn' => 'name',
+ 'labelColumn' => 'label',
+ 'nameColumn' => 'name',
],
'add' => '1.1',
],
'localizable' => 0,
'FKClassName' => 'CRM_Contact_DAO_Contact',
'html' => [
+ 'type' => 'EntityRef',
'label' => ts("Created By"),
],
'add' => '3.4',
'token' => FALSE,
],
'where' => 'civicrm_tag.created_date',
+ 'default' => 'CURRENT_TIMESTAMP',
'table_name' => 'civicrm_tag',
'entity' => 'Tag',
'bao' => 'CRM_Core_BAO_Tag',
'localizable' => 0,
+ 'html' => [
+ 'type' => 'Select Date',
+ 'formatType' => 'activityDateTime',
+ 'label' => ts("Created Date"),
+ ],
+ 'readonly' => TRUE,
'add' => '3.4',
],
];
$this->applyFilter('__ALL__', 'trim');
- $this->add('text', 'name', ts('Name'),
- CRM_Core_DAO::getAttribute('CRM_Core_DAO_Tag', 'name'), TRUE
+ $this->add('text', 'label', ts('Label'),
+ CRM_Core_DAO::getAttribute('CRM_Core_DAO_Tag', 'label'), TRUE
);
- $this->addRule('name', ts('Name already exists in Database.'), 'objectExists', [
- 'CRM_Core_DAO_Tag',
- $this->_id,
- ]);
$this->add('text', 'description', ts('Description'),
CRM_Core_DAO::getAttribute('CRM_Core_DAO_Tag', 'description')
if (empty($this->_id) && $cloneFrom) {
$params = ['id' => $cloneFrom];
CRM_Core_BAO_Tag::retrieve($params, $this->_values);
- $this->_values['name'] .= ' (' . ts('copy') . ')';
+ $this->_values['label'] .= ' (' . ts('copy') . ')';
if (!empty($this->_values['is_reserved']) && !CRM_Core_Permission::check('administer reserved tags')) {
$this->_values['is_reserved'] = 0;
}
}
if (count($this->_id) == 1 && $deleted == 1) {
if ($tag['is_tagset']) {
- CRM_Core_Session::setStatus(ts("The tag set '%1' has been deleted.", [1 => $tag['name']]), ts('Deleted'), 'success');
+ CRM_Core_Session::setStatus(ts("The tag set '%1' has been deleted.", [1 => $tag['label']]), ts('Deleted'), 'success');
}
else {
- CRM_Core_Session::setStatus(ts("The tag '%1' has been deleted.", [1 => $tag['name']]), ts('Deleted'), 'success');
+ CRM_Core_Session::setStatus(ts("The tag '%1' has been deleted.", [1 => $tag['label']]), ts('Deleted'), 'success');
}
}
else {
$params['is_selectable'] = 0;
}
$tag = CRM_Core_BAO_Tag::add($params);
- CRM_Core_Session::setStatus(ts("The tag '%1' has been saved.", [1 => $tag->name]), ts('Saved'), 'success');
+ CRM_Core_Session::setStatus(ts("The tag '%1' has been saved.", [1 => $tag->label]), ts('Saved'), 'success');
$this->ajaxResponse['tag'] = $tag->toArray();
}
CRM_Core_Session::singleton()->pushUserContext(CRM_Utils_System::url('civicrm/tag'));
}
$result = civicrm_api3('Tag', 'get', [
- 'return' => ["name", "used_for", "description", "created_id.display_name", "created_date", "is_reserved"],
+ 'return' => ["name", "label", "used_for", "description", "created_id.display_name", "created_date", "is_reserved"],
'is_tagset' => 1,
'options' => ['limit' => 0],
]);
* The version number matching this function name
*/
public function upgrade_5_68_alpha1($rev): void {
+ // Add column prior to updating it via runSql
+ $this->addTask('Add Tag.label field', 'addColumn', 'civicrm_tag', 'label', "varchar(64) NOT NULL COMMENT 'User-facing tag name' AFTER `name`");
+ $this->addTask('Update Tag.name field', 'alterColumn', 'civicrm_tag', 'name', "varchar(64) NOT NULL COMMENT 'Unique machine name'");
+ $this->addTask('Update Tag.created_date field', 'alterColumn', 'civicrm_tag', 'created_date', "datetime DEFAULT CURRENT_TIMESTAMP COMMENT 'Date and time that tag was created.'");
$this->addTask(ts('Upgrade DB to %1: SQL', [1 => $rev]), 'runSql', $rev);
}
{* file to handle db changes in 5.68.alpha1 during upgrade *}
+
+UPDATE `civicrm_tag` SET `label` = `name` WHERE `label` = '';
*/
public function modifySpec(RequestSpec $spec) {
$spec->getFieldByName('used_for')->setDefaultValue('civicrm_contact');
+ $spec->getFieldByName('name')->setRequired(FALSE)->setRequiredIf('empty($values.label)');
+ $spec->getFieldByName('label')->setRequired(FALSE)->setRequiredIf('empty($values.name)');
}
/**
* @param null $extraOutput
* @return array|int
*/
- public function callAPIFailure($entity, $action, $params, $expectedErrorMessage = NULL, $extraOutput = NULL) {
+ public function callAPIFailure($entity, $action, $params = [], $expectedErrorMessage = NULL, $extraOutput = NULL) {
if (is_array($params)) {
$params += [
'version' => $this->_apiversion,
*/
function _civicrm_api3_tag_create_spec(&$params) {
$params['used_for']['api.default'] = 'civicrm_contact';
- $params['name']['api.required'] = 1;
$params['id']['api.aliases'] = ['tag'];
}
->setLoadOptions(['id', 'label'])
->execute()->first()['options'],
'tags' => Tag::get()
- ->addSelect('id', 'name', 'color', 'is_selectable', 'description')
+ ->addSelect('id', 'label', 'color', 'is_selectable', 'description')
->addWhere('used_for', 'CONTAINS', 'civicrm_saved_search')
->execute(),
];
modules.push({text: label, id: key});
}, []), 'text');
this.getTags = function() {
- return {results: formatForSelect2(CRM.crmSearchAdmin.tags, 'id', 'name', ['color', 'description'])};
+ return {results: formatForSelect2(CRM.crmSearchAdmin.tags, 'id', 'label', ['color', 'description'])};
};
this.getPrimaryEntities = function() {
}
};
- this.makeTag = function(name) {
+ this.makeTag = function(label) {
crmApi4('Tag', 'create', {
- values: {name: name, color: ctrl.color, is_selectable: true, used_for: ['civicrm_saved_search']}
+ values: {label: label, color: ctrl.color, is_selectable: true, used_for: ['civicrm_saved_search']}
}, 0).then(function(tag) {
ctrl.allTags.push(tag);
ctrl.toggleTag(tag);
<a href ng-click="$ctrl.makeTag($ctrl.search)">{{ $ctrl.search }}</a>
</div>
</li>
- <li ng-repeat="tag in $ctrl.allTags | filter:{name: $ctrl.search, is_selectable: true}">
+ <li ng-repeat="tag in $ctrl.allTags | filter:{label: $ctrl.search, is_selectable: true}">
<a href ng-click="$ctrl.toggleTag(tag)">
<i class="crm-i fa-check" style="visibility: {{ $ctrl.hasTag(tag) ? 'visible' : 'hidden' }}"></i>
<span class="crm-search-admin-tag-color" style="background-color: {{:: tag.color }}"></span>
- {{:: tag.name }}
+ {{:: tag.label }}
</a>
</li>
</ul>
<span class="badge" ng-repeat="id in $ctrl.tagIds" style="{{:: $ctrl.getStyle(id) }}">
- {{:: $ctrl.getTag(id).name }}
+ {{:: $ctrl.getTag(id).label }}
</span>
crmApi4({
tags: ['Tag', 'get', {
- select: ['id', 'name', 'color', 'description', 'is_selectable', 'parent_id'],
+ select: ['id', 'label', 'color', 'description', 'is_selectable', 'parent_id'],
where: [
['is_tagset', '=', false],
['used_for:name', 'CONTAINS', this.entity],
['OR', [['parent_id', 'IS NULL'], ['parent_id.is_tagset', '=', false]]]
],
- orderBy: {name: 'ASC'}
+ orderBy: {label: 'ASC'}
}],
tagsets: ['Tag', 'get', {
- select: ['id', 'name'],
+ select: ['id', 'name', 'label'],
where: [['is_tagset', '=', true], ['used_for:name', 'CONTAINS', this.entity]]
}],
}).then(function(result) {
var sorted = _.transform(rawTags, function(sorted, tag) {
sorted[tag.id] = {
id: tag.id,
- text: tag.name,
+ text: tag.label,
description: tag.description,
color: tag.color,
disabled: !tag.is_selectable,
>
</div>
<div ng-repeat="tagset in $ctrl.tagsets" class="form-inline">
- <label>{{:: tagset.name }}</label>
+ <label>{{:: tagset.label }}</label>
<input
ng-model="$ctrl.selectedTagsetTags[tagset.name]"
ng-list
])
->addValues([
[
- 'name' => ts('Non-profit'),
+ 'label' => ts('Non-profit'),
+ 'name' => 'Non_profit',
'description' => ts('Any not-for-profit organization.'),
+ 'color' => '#0bcb21',
],
[
- 'name' => ts('Company'),
+ 'label' => ts('Company'),
+ 'name' => 'Company',
'description' => ts('For-profit organization.'),
+ 'color' => '#2260c3',
],
[
- 'name' => ts('Government Entity'),
+ 'label' => ts('Government Entity'),
+ 'name' => 'Government_Entity',
'description' => ts('Any governmental entity.'),
+ 'color' => '#cd4b13',
],
[
- 'name' => ts('Major Donor'),
+ 'label' => ts('Major Donor'),
+ 'name' => 'Major_Donor',
'description' => ts('High-value supporter of our organization.'),
+ 'color' => '#0cdae9',
],
[
- 'name' => ts('Volunteer'),
+ 'label' => ts('Volunteer'),
+ 'name' => 'Volunteer',
'description' => ts('Active volunteers.'),
+ 'color' => '#f0dc00',
],
]);
{if $action eq 1 or $action eq 2}
<table class="form-layout-compressed">
<tr class="crm-tag-form-block-label">
- <td class="label">{$form.name.label}</td>
- <td>{$form.name.html}</td>
+ <td class="label">{$form.label.label}</td>
+ <td>{$form.label.html}</td>
</tr>
<tr class="crm-tag-form-block-description">
<td class="label">{$form.description.label}</td>
</li>
{foreach from=$tagsets item=set}
<li class="ui-corner-all crm-tab-button {if ($set.is_reserved)}is-reserved{/if}" title="{ts 1=', '|implode:$set.used_for_label}Tag Set for %1{/ts}">
- <a href="#tagset-{$set.id}">{$set.name}</a>
+ <a href="#tagset-{$set.id}">{$set.label}</a>
</li>
{/foreach}
{if call_user_func(array('CRM_Core_Permission','check'), 'administer Tagsets')}
function updateTagset(info) {
tagSets[tagset].description = info.description;
- tagSets[tagset].name = info.name;
+ tagSets[tagset].label = info.label;
tagSets[tagset].used_for = info.used_for;
tagSets[tagset].is_reserved = info.is_reserved;
formatTagSet(tagSets[tagset]);
function addTagsetHeader() {
$('.tagset-header', $panel).remove();
$panel.prepend(tagsetHeaderTpl(tagSets[tagset]));
- $("a[href='#tagset-" + tagset + "']").text(tagSets[tagset].name)
+ $("a[href='#tagset-" + tagset + "']").text(tagSets[tagset].label)
.parent().toggleClass('is-reserved', tagSets[tagset].is_reserved == 1)
.attr('title', ts('{/literal}{ts escape='js' 1='%1'}Tag Set for %1{/ts}{literal}', {'1': tagSets[tagset].used_for_label.join(', ')}));
}
e.preventDefault();
var sets = [{key: '0', value: '{/literal}{ts escape='js'}Main Tag Tree{/ts}{literal}'}];
_.each(tagSets, function(tagSet) {
- sets.push({key: tagSet.id, value: tagSet.name});
+ sets.push({key: tagSet.id, value: tagSet.label});
});
CRM.confirm({
title: '{/literal}{ts escape='js'}Move to Tagset{/ts}{literal}',
tagSets[data.tag.id].display_name = user.display_name;
formatTagSet(tagSets[data.tag.id]);
$("#new-tagset").before('<div id="tagset-' + data.tag.id + '">');
- $("a[href='#new-tagset']").parent().before('<li class="ui-corner-all crm-tab-button"><a href="#tagset-' + data.tag.id + '">' + data.tag.name + '</a></li>');
+ $("a[href='#new-tagset']").parent().before('<li class="ui-corner-all crm-tab-button"><a href="#tagset-' + data.tag.id + '">' + data.tag.label + '</a></li>');
$('#mainTabContainer').tabs('refresh');
$('#mainTabContainer').tabs('option', 'active', -2);
});
<div class="crm-entity" data-entity="Tag" data-id="<%= id %>">
<h4>
<input type="color" value="<%= data.color %>" <% if (!data.is_reserved || adminReserved) {ldelim} %>title="{ts}Select color{/ts}" <% {rdelim} else {ldelim} %>disabled<% {rdelim} %> />
- <span class="<% if (!data.is_reserved || adminReserved) {ldelim} %>crm-editable<% {rdelim} %>" data-field="name"><%- text %></span>
+ <span class="<% if (!data.is_reserved || adminReserved) {ldelim} %>crm-editable<% {rdelim} %>" data-field="label"><%- text %></span>
</h4>
<hr />
<div><span class="tdl">{ts}Description:{/ts}</span>
// Create an example hierarchy of tags.
// The family tree of Abraham is used as a well known example of a hierarchy (no statement intended).
// The order of ids is important because of: https://lab.civicrm.org/dev/core/-/issues/4049, that's why we create Isaac before Abraham.
- CRM_Core_DAO::executeQuery("INSERT INTO civicrm_tag (id,name,used_for,is_tagset) VALUES(1, 'Isaac', 'civicrm_contact', 0);");
- CRM_Core_DAO::executeQuery("INSERT INTO civicrm_tag (id,name,used_for,is_tagset) VALUES(2, 'Abraham', 'civicrm_contact', 0);");
- CRM_Core_DAO::executeQuery("INSERT INTO civicrm_tag (id,name,used_for,is_tagset) VALUES(3, 'Jacob', 'civicrm_contact', 0);");
- CRM_Core_DAO::executeQuery("INSERT INTO civicrm_tag (id,name,used_for,is_tagset) VALUES(4, 'Ishmael', 'civicrm_contact', 1);");
- CRM_Core_DAO::executeQuery("INSERT INTO civicrm_tag (id,name,used_for,is_tagset) VALUES(5, 'Kedar', 'civicrm_contact', 1);");
- CRM_Core_DAO::executeQuery("INSERT INTO civicrm_tag (id,name,used_for,is_tagset) VALUES(6, 'Working', 'civicrm_activity', 1);");
- CRM_Core_DAO::executeQuery("INSERT INTO civicrm_tag (id,name,used_for,is_tagset) VALUES(7, 'Eating', 'civicrm_activity', 1);");
+ CRM_Core_DAO::executeQuery("
+ INSERT INTO civicrm_tag (id, name, label, used_for, is_tagset)
+ VALUES
+ (1, 'Isaac', 'Isaac', 'civicrm_contact', 0),
+ (2, 'Abraham', 'Abraham', 'civicrm_contact', 0),
+ (3, 'Jacob', 'Jacob', 'civicrm_contact', 0),
+ (4, 'Ishmael', 'Ishmael', 'civicrm_contact', 1),
+ (5, 'Kedar', 'Kedar', 'civicrm_contact', 1),
+ (6, 'Working', 'Working', 'civicrm_activity', 1),
+ (7, 'Eating', 'Eating', 'civicrm_activity', 1);
+ ");
// Isaac is the son of abraham
CRM_Core_DAO::executeQuery("UPDATE civicrm_tag SET parent_id = 2 WHERE name = 'Isaac';");
*/
public function testCreateEmptyParams($version) {
$this->_apiversion = $version;
- $result = $this->callAPIFailure('tag', 'create', [], 'name');
+ $result = $this->callAPIFailure('tag', 'create');
}
/**
$options = array_column($options, NULL, 'name');
$this->assertEquals('colorful', $options[$tag]['description']);
$this->assertEquals('#aabbcc', $options[$tag]['color']);
+ $this->assertEquals($tag, $options[$tag]['name']);
$this->assertEquals($tag, $options[$tag]['label']);
}
<pseudoconstant>
<table>civicrm_tag</table>
<keyColumn>id</keyColumn>
- <labelColumn>name</labelColumn>
+ <nameColumn>name</nameColumn>
+ <labelColumn>label</labelColumn>
<condition>is_tagset != 1</condition>
</pseudoconstant>
<html>
<add>1.1</add>
<log>true</log>
<icon>fa-tag</icon>
- <labelField>name</labelField>
+ <labelField>label</labelField>
<field>
<name>id</name>
<title>Tag ID</title>
<type>varchar</type>
<required>true</required>
<length>64</length>
- <comment>Name of Tag.</comment>
+ <comment>Unique machine name</comment>
<add>1.1</add>
</field>
+ <!-- TODO: Localizable -->
+ <field>
+ <name>label</name>
+ <title>Tag Label</title>
+ <comment>User-facing tag name</comment>
+ <required>true</required>
+ <type>varchar</type>
+ <length>64</length>
+ <html>
+ <type>Text</type>
+ </html>
+ <add>5.68</add>
+ </field>
+ <!-- TODO: Localizable -->
<field>
<name>description</name>
<title>Description</title>
<pseudoconstant>
<table>civicrm_tag</table>
<keyColumn>id</keyColumn>
- <labelColumn>name</labelColumn>
+ <nameColumn>name</nameColumn>
+ <labelColumn>label</labelColumn>
</pseudoconstant>
<html>
<label>Parent Tag</label>
<comment>FK to civicrm_contact, who created this tag</comment>
<html>
<label>Created By</label>
+ <type>EntityRef</type>
</html>
<add>3.4</add>
</field>
<type>datetime</type>
<title>Tag Created Date</title>
<comment>Date and time that tag was created.</comment>
+ <default>CURRENT_TIMESTAMP</default>
+ <readonly>true</readonly>
+ <html>
+ <type>Select Date</type>
+ <formatType>activityDateTime</formatType>
+ <label>Created Date</label>
+ </html>
<add>3.4</add>
</field>
</table>