mirror of
https://codeberg.org/artfulrobot/contactcats.git
synced 2025-06-26 07:28:05 +02:00
Fixes and tidies
This commit is contained in:
parent
e56be4ce31
commit
69d4c6b2e8
11 changed files with 191 additions and 40 deletions
|
@ -125,7 +125,7 @@ class Processor {
|
||||||
$oldCategoryId = (int) ($lastChange[0] ?? 0);
|
$oldCategoryId = (int) ($lastChange[0] ?? 0);
|
||||||
$newCategoryId = (int) ($lastChange[1] ?? 0);
|
$newCategoryId = (int) ($lastChange[1] ?? 0);
|
||||||
$oldName = $this->categories[$oldCategoryId]['label'] ?? E::ts('(Unknown)');
|
$oldName = $this->categories[$oldCategoryId]['label'] ?? E::ts('(Unknown)');
|
||||||
$subject = "$oldName → " . $this->categories[$newCategoryId];
|
$subject = "$oldName → " . $this->categories[$newCategoryId]['label'];
|
||||||
// Create activity on the first contact
|
// Create activity on the first contact
|
||||||
$a = Activity::create(FALSE)
|
$a = Activity::create(FALSE)
|
||||||
->addValue('target_contact_id', $batch[0])
|
->addValue('target_contact_id', $batch[0])
|
||||||
|
@ -139,18 +139,18 @@ class Processor {
|
||||||
CRM_Core_DAO::executeQuery("INSERT INTO civicrm_activity_contact (contact_id, activity_id, record_type_id)
|
CRM_Core_DAO::executeQuery("INSERT INTO civicrm_activity_contact (contact_id, activity_id, record_type_id)
|
||||||
SELECT id contact_id, $activityID activity_id, 3 record_type_id
|
SELECT id contact_id, $activityID activity_id, 3 record_type_id
|
||||||
FROM civicrm_contact_category cc
|
FROM civicrm_contact_category cc
|
||||||
WHERE cc.category = $oldCategoryId
|
WHERE cc.category_definition_id = $oldCategoryId
|
||||||
AND cc.next_category = $newCategoryId
|
AND cc.next_category = $newCategoryId
|
||||||
AND contact_id <> $batch[0]
|
AND cc.id <> $batch[0]
|
||||||
")->free();
|
")->free();
|
||||||
Civi::log()->debug(count($batch) . " changes: $subject");
|
Civi::log()->debug(count($batch) . " changes: $subject");
|
||||||
};
|
};
|
||||||
|
|
||||||
while ($changes->fetch()) {
|
while ($changes->fetch()) {
|
||||||
$n++;
|
$n++;
|
||||||
if ($lastChange[0] !== $changes->category || $lastChange[1] !== $changes->next_category) {
|
if ($lastChange[0] !== $changes->category_definition_id || $lastChange[1] !== $changes->next_category) {
|
||||||
$writeBatch();
|
$writeBatch();
|
||||||
$lastChange = [$changes->category, $changes->next_category];
|
$lastChange = [$changes->category_definition_id, $changes->next_category];
|
||||||
$batch = [];
|
$batch = [];
|
||||||
}
|
}
|
||||||
$batch[] = $changes->id;
|
$batch[] = $changes->id;
|
||||||
|
@ -195,7 +195,7 @@ class Processor {
|
||||||
// Q: is it quicker to do a WHERE NOT EXISTS? A: nope.
|
// Q: is it quicker to do a WHERE NOT EXISTS? A: nope.
|
||||||
CRM_Core_DAO::executeQuery(<<<SQL
|
CRM_Core_DAO::executeQuery(<<<SQL
|
||||||
INSERT INTO civicrm_contact_category
|
INSERT INTO civicrm_contact_category
|
||||||
SELECT id, id contact_id, NULL as category_definition_id, 0 next_category
|
SELECT id, NULL as category_definition_id, 0 next_category
|
||||||
FROM civicrm_contact
|
FROM civicrm_contact
|
||||||
WHERE NOT EXISTS (SELECT id FROM civicrm_contact_category WHERE id = civicrm_contact.id)
|
WHERE NOT EXISTS (SELECT id FROM civicrm_contact_category WHERE id = civicrm_contact.id)
|
||||||
SQL)->free();
|
SQL)->free();
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
<div af-fieldset="">
|
|
||||||
<crm-search-display-list search-name="Category_for_contact" display-name="Category_for_contact_List_1" filters="{'contact_id': options.contact_id}"></crm-search-display-list>
|
|
||||||
</div>
|
|
|
@ -1,13 +0,0 @@
|
||||||
{
|
|
||||||
"type": "search",
|
|
||||||
"title": "Category",
|
|
||||||
"placement": [
|
|
||||||
"contact_summary_block"
|
|
||||||
],
|
|
||||||
"icon": "fa-list-alt",
|
|
||||||
"server_route": "",
|
|
||||||
"permission": [
|
|
||||||
"access CiviCRM"
|
|
||||||
],
|
|
||||||
"permission_operator": "AND"
|
|
||||||
}
|
|
3
ang/afsearchContactCategoryCounts.aff.html
Normal file
3
ang/afsearchContactCategoryCounts.aff.html
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<div af-fieldset="">
|
||||||
|
<crm-search-display-table search-name="SavedSearch_Contact_Category_Counts" display-name="Category_counts"></crm-search-display-table>
|
||||||
|
</div>
|
33
ang/afsearchContactCategoryCounts.aff.json
Normal file
33
ang/afsearchContactCategoryCounts.aff.json
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
{
|
||||||
|
"type": "search",
|
||||||
|
"title": "Contact Category Counts",
|
||||||
|
"placement": [
|
||||||
|
"dashboard_dashlet"
|
||||||
|
],
|
||||||
|
"icon": "fa-tags",
|
||||||
|
"server_route": "civicrm/reports/contact-category-counts",
|
||||||
|
"permission": [
|
||||||
|
"access CiviCRM"
|
||||||
|
],
|
||||||
|
"permission_operator": "AND",
|
||||||
|
"navigation": {
|
||||||
|
"parent": "Reports",
|
||||||
|
"label": "Contact Category Counts",
|
||||||
|
"weight": 0
|
||||||
|
},
|
||||||
|
"modified_date": "2025-02-27 17:32:42",
|
||||||
|
"requires": null,
|
||||||
|
"entity_type": null,
|
||||||
|
"join_entity": null,
|
||||||
|
"description": null,
|
||||||
|
"summary_contact_type": null,
|
||||||
|
"summary_weight": null,
|
||||||
|
"is_public": false,
|
||||||
|
"redirect": null,
|
||||||
|
"submit_enabled": true,
|
||||||
|
"submit_limit": null,
|
||||||
|
"create_submission": null,
|
||||||
|
"manual_processing": null,
|
||||||
|
"allow_verification_by_email": null,
|
||||||
|
"email_confirmation_template_id": null
|
||||||
|
}
|
|
@ -27,6 +27,10 @@
|
||||||
ctrl.categoryToEdit = null;
|
ctrl.categoryToEdit = null;
|
||||||
ctrl.categoryDefinitions = null;
|
ctrl.categoryDefinitions = null;
|
||||||
ctrl.categoryDefinitions = await crmApi4("ContactCategoryDefinition", 'get', { orderBy: { execution_order: 'ASC' }, withLabels: true });
|
ctrl.categoryDefinitions = await crmApi4("ContactCategoryDefinition", 'get', { orderBy: { execution_order: 'ASC' }, withLabels: true });
|
||||||
|
if (ctrl.categoryDefinitions.count === 0) {
|
||||||
|
// First time.
|
||||||
|
ctrl.categoryDefinitions = [];
|
||||||
|
}
|
||||||
// Ensure we have the minimum of what we need.
|
// Ensure we have the minimum of what we need.
|
||||||
if (!ctrl.categoryDefinitions.find(c => c.search_type === 'default')) {
|
if (!ctrl.categoryDefinitions.find(c => c.search_type === 'default')) {
|
||||||
// There's no default one.
|
// There's no default one.
|
||||||
|
@ -80,7 +84,7 @@
|
||||||
// Create a blank
|
// Create a blank
|
||||||
ctrl.categoryToEdit = {
|
ctrl.categoryToEdit = {
|
||||||
id: 0,
|
id: 0,
|
||||||
execution_order: ctrl.categoryDefinitions.length,
|
execution_order: -1,
|
||||||
label: '',
|
label: '',
|
||||||
search_type: 'search',
|
search_type: 'search',
|
||||||
search_data: { saved_search_id: null },
|
search_data: { saved_search_id: null },
|
||||||
|
@ -139,8 +143,14 @@
|
||||||
edited.search_data = {saved_search_id};
|
edited.search_data = {saved_search_id};
|
||||||
}
|
}
|
||||||
|
|
||||||
const idx = edited.execution_order;
|
if (edited.execution_order === -1) {
|
||||||
ctrl.categoryDefinitions[idx] = edited;
|
// This is a new category, we need to insert it before the default one.
|
||||||
|
const newIdx = ctrl.categoryDefinitions.length - 1;
|
||||||
|
ctrl.categoryDefinitions.splice(newIdx, 0, edited);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ctrl.categoryDefinitions[edited.execution_order] = edited;
|
||||||
|
}
|
||||||
ctrl.categoryToEdit = null;
|
ctrl.categoryToEdit = null;
|
||||||
updateOrders();
|
updateOrders();
|
||||||
ctrl.dirty = 'dirty';
|
ctrl.dirty = 'dirty';
|
||||||
|
|
|
@ -17,9 +17,7 @@ return [
|
||||||
'style' => 'Inline',
|
'style' => 'Inline',
|
||||||
'help_pre' => E::ts(''),
|
'help_pre' => E::ts(''),
|
||||||
'help_post' => E::ts(''),
|
'help_post' => E::ts(''),
|
||||||
'weight' => 18,
|
|
||||||
'collapse_adv_display' => TRUE,
|
'collapse_adv_display' => TRUE,
|
||||||
'created_date' => '2025-02-20 13:59:06',
|
|
||||||
'is_public' => FALSE,
|
'is_public' => FALSE,
|
||||||
'icon' => '',
|
'icon' => '',
|
||||||
],
|
],
|
||||||
|
@ -35,7 +33,7 @@ return [
|
||||||
'version' => 4,
|
'version' => 4,
|
||||||
'values' => [
|
'values' => [
|
||||||
'custom_group_id.name' => 'Category_changes',
|
'custom_group_id.name' => 'Category_changes',
|
||||||
'name' => 'Previous_Category',
|
'name' => 'previous_category_id',
|
||||||
'label' => E::ts('Previous Category'),
|
'label' => E::ts('Previous Category'),
|
||||||
'data_type' => 'EntityReference',
|
'data_type' => 'EntityReference',
|
||||||
'html_type' => 'Autocomplete-Select',
|
'html_type' => 'Autocomplete-Select',
|
||||||
|
@ -44,7 +42,7 @@ return [
|
||||||
'text_length' => 255,
|
'text_length' => 255,
|
||||||
'note_columns' => 60,
|
'note_columns' => 60,
|
||||||
'note_rows' => 4,
|
'note_rows' => 4,
|
||||||
'column_name' => 'previous_category_117',
|
'column_name' => 'previous_category_id',
|
||||||
'fk_entity' => 'ContactCategoryDefinition',
|
'fk_entity' => 'ContactCategoryDefinition',
|
||||||
],
|
],
|
||||||
'match' => [
|
'match' => [
|
||||||
|
@ -62,7 +60,7 @@ return [
|
||||||
'version' => 4,
|
'version' => 4,
|
||||||
'values' => [
|
'values' => [
|
||||||
'custom_group_id.name' => 'Category_changes',
|
'custom_group_id.name' => 'Category_changes',
|
||||||
'name' => 'New_Category',
|
'name' => 'new_category_id',
|
||||||
'label' => E::ts('New Category'),
|
'label' => E::ts('New Category'),
|
||||||
'data_type' => 'EntityReference',
|
'data_type' => 'EntityReference',
|
||||||
'html_type' => 'Autocomplete-Select',
|
'html_type' => 'Autocomplete-Select',
|
||||||
|
@ -71,7 +69,7 @@ return [
|
||||||
'text_length' => 255,
|
'text_length' => 255,
|
||||||
'note_columns' => 60,
|
'note_columns' => 60,
|
||||||
'note_rows' => 4,
|
'note_rows' => 4,
|
||||||
'column_name' => 'new_category_118',
|
'column_name' => 'new_category_id',
|
||||||
'fk_entity' => 'ContactCategoryDefinition',
|
'fk_entity' => 'ContactCategoryDefinition',
|
||||||
],
|
],
|
||||||
'match' => [
|
'match' => [
|
||||||
|
|
26
managed/OptionValue_Changed_category.mgd.php
Normal file
26
managed/OptionValue_Changed_category.mgd.php
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<?php
|
||||||
|
use CRM_Contactcats_ExtensionUtil as E;
|
||||||
|
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
'name' => 'OptionValue_Changed_category',
|
||||||
|
'entity' => 'OptionValue',
|
||||||
|
'cleanup' => 'unused',
|
||||||
|
'update' => 'unmodified',
|
||||||
|
'params' => [
|
||||||
|
'version' => 4,
|
||||||
|
'values' => [
|
||||||
|
'option_group_id.name' => 'activity_type',
|
||||||
|
'label' => E::ts('Changed category'),
|
||||||
|
'name' => 'changed_contact_category',
|
||||||
|
'description' => E::ts('<p>This activity is automatically added when a contact is moved from one category to another.</p>'),
|
||||||
|
'icon' => 'fa-tags',
|
||||||
|
],
|
||||||
|
'match' => [
|
||||||
|
// Should this be option_group_id.name?
|
||||||
|
'option_group_id',
|
||||||
|
'name',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
104
managed/SavedSearch_SavedSearch_Contact_Category_Counts.mgd.php
Normal file
104
managed/SavedSearch_SavedSearch_Contact_Category_Counts.mgd.php
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
<?php
|
||||||
|
use CRM_Contactcats_ExtensionUtil as E;
|
||||||
|
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
'name' => 'SavedSearch_SavedSearch_Contact_Category_Counts',
|
||||||
|
'entity' => 'SavedSearch',
|
||||||
|
'cleanup' => 'unused',
|
||||||
|
'update' => 'unmodified',
|
||||||
|
'params' => [
|
||||||
|
'version' => 4,
|
||||||
|
'values' => [
|
||||||
|
'name' => 'SavedSearch_Contact_Category_Counts',
|
||||||
|
'label' => E::ts('Category Counts query'),
|
||||||
|
'api_entity' => 'ContactCategoryDefinition',
|
||||||
|
'api_params' => [
|
||||||
|
'version' => 4,
|
||||||
|
'select' => [
|
||||||
|
'id',
|
||||||
|
'label',
|
||||||
|
'color',
|
||||||
|
'icon',
|
||||||
|
'COUNT(ContactCategoryDefinition_ContactCategory_category_definition_id_01.id) AS COUNT_ContactCategoryDefinition_ContactCategory_category_definition_id_01_id',
|
||||||
|
],
|
||||||
|
'orderBy' => [],
|
||||||
|
'where' => [],
|
||||||
|
'groupBy' => ['id'],
|
||||||
|
'join' => [
|
||||||
|
[
|
||||||
|
'ContactCategory AS ContactCategoryDefinition_ContactCategory_category_definition_id_01',
|
||||||
|
'LEFT',
|
||||||
|
[
|
||||||
|
'id',
|
||||||
|
'=',
|
||||||
|
'ContactCategoryDefinition_ContactCategory_category_definition_id_01.category_definition_id',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'having' => [],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'match' => ['name'],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'SavedSearch_SavedSearch_Contact_Category_Counts_SearchDisplay_Category_counts',
|
||||||
|
'entity' => 'SearchDisplay',
|
||||||
|
'cleanup' => 'unused',
|
||||||
|
'update' => 'unmodified',
|
||||||
|
'params' => [
|
||||||
|
'version' => 4,
|
||||||
|
'values' => [
|
||||||
|
'name' => 'Category_counts',
|
||||||
|
'label' => E::ts('Category counts'),
|
||||||
|
'saved_search_id.name' => 'SavedSearch_Contact_Category_Counts',
|
||||||
|
'type' => 'table',
|
||||||
|
'settings' => [
|
||||||
|
'description' => E::ts('Shows a list of all categories and how many contacts are in each one.'),
|
||||||
|
'sort' => [
|
||||||
|
['label', 'ASC'],
|
||||||
|
],
|
||||||
|
'limit' => 50,
|
||||||
|
'pager' => FALSE,
|
||||||
|
'placeholder' => 0,
|
||||||
|
'columns' => [
|
||||||
|
[
|
||||||
|
'type' => 'field',
|
||||||
|
'key' => 'label',
|
||||||
|
'dataType' => 'String',
|
||||||
|
'label' => E::ts('Category'),
|
||||||
|
'sortable' => TRUE,
|
||||||
|
'rewrite' => '',
|
||||||
|
'icons' => [
|
||||||
|
[
|
||||||
|
'field' => 'icon',
|
||||||
|
'side' => 'left',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'field' => 'icon',
|
||||||
|
'side' => 'left',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'cssRules' => [],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'type' => 'field',
|
||||||
|
'key' => 'COUNT_ContactCategoryDefinition_ContactCategory_category_definition_id_01_id',
|
||||||
|
'dataType' => 'Integer',
|
||||||
|
'label' => E::ts('Count'),
|
||||||
|
'sortable' => TRUE,
|
||||||
|
'alignment' => 'text-right',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'actions' => FALSE,
|
||||||
|
'classes' => ['table', 'table-striped'],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'match' => [
|
||||||
|
'saved_search_id',
|
||||||
|
'name',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
|
@ -27,13 +27,6 @@ return [
|
||||||
'description' => E::ts('Unique ID, corresponds to contact id'),
|
'description' => E::ts('Unique ID, corresponds to contact id'),
|
||||||
'primary_key' => TRUE,
|
'primary_key' => TRUE,
|
||||||
'auto_increment' => TRUE,
|
'auto_increment' => TRUE,
|
||||||
],
|
|
||||||
'contact_id' => [
|
|
||||||
'title' => E::ts('Contact ID'),
|
|
||||||
'sql_type' => 'int unsigned',
|
|
||||||
'input_type' => 'EntityRef',
|
|
||||||
'required' => TRUE,
|
|
||||||
'description' => E::ts('Same as id but for FormBuilder'),
|
|
||||||
'input_attrs' => [
|
'input_attrs' => [
|
||||||
'label' => E::ts('Contact'),
|
'label' => E::ts('Contact'),
|
||||||
],
|
],
|
||||||
|
@ -64,7 +57,7 @@ return [
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
'next_category' => [
|
'next_category' => [
|
||||||
'title' => E::ts('Next Category'),
|
'title' => E::ts('Next Category - internal use'),
|
||||||
'sql_type' => 'int unsigned',
|
'sql_type' => 'int unsigned',
|
||||||
'required' => TRUE,
|
'required' => TRUE,
|
||||||
'default' => 0,
|
'default' => 0,
|
||||||
|
|
|
@ -66,7 +66,7 @@ return [
|
||||||
'icon' => [
|
'icon' => [
|
||||||
'title' => E::ts('Icon'),
|
'title' => E::ts('Icon'),
|
||||||
'sql_type' => 'varchar(64)',
|
'sql_type' => 'varchar(64)',
|
||||||
'default' => '',
|
'default' => 'fa-circle-half-stroke',
|
||||||
'required' => TRUE,
|
'required' => TRUE,
|
||||||
'description' => E::ts('The name of a Font Awesome icon to use to represent this, e.g. fa-trophy'),
|
'description' => E::ts('The name of a Font Awesome icon to use to represent this, e.g. fa-trophy'),
|
||||||
],
|
],
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue