diff --git a/CRM/Contactcats/BAO/ContactCategoryDefinition.php b/CRM/Contactcats/BAO/ContactCategoryDefinition.php new file mode 100644 index 0000000..e499082 --- /dev/null +++ b/CRM/Contactcats/BAO/ContactCategoryDefinition.php @@ -0,0 +1,7 @@ + $row) { + if ($row['search_type'] === 'group') { + $groupIDs[] = $row['search_data']['group_id'] ?? NULL; + } + elseif ($row['search_type'] === 'search') { + $searchIDs[] = $row['search_data']['saved_search_id'] ?? NULL; + } + } + $groupIDs = array_filter($groupIDs); + $searchIDs = array_filter($searchIDs); + if ($groupIDs) { + $groupNames = Group::get() + ->addWhere('id', 'IN', $groupIDs) + ->addSelect('title') + ->execute()->indexBy('id')->column('title'); + } + if ($searchIDs) { + $searchNames = SavedSearch::get() + ->addWhere('id', 'IN', $searchIDs) + ->addSelect('label') + ->execute()->indexBy('id')->column('label'); + } + if ($searchNames || $groupNames) { + foreach ($result as $row) { + if ($row['search_type'] === 'group' + && !empty($groupNames[$row['search_data']['group_id'] ?? '']) + ) { + $row['search_source'] = $groupNames[$row['search_data']['group_id'] ?? '']; + } + elseif (($row['search_type'] === 'search') + && !empty($searchNames[$row['search_data']['saved_search_id'] ?? '']) + ) { + $row['search_source'] = $searchNames[$row['search_data']['saved_search_id'] ?? '']; + } + } + } + $result[$idx] = $row; + } + +} diff --git a/Civi/Api4/ContactCategoryDefinition.php b/Civi/Api4/ContactCategoryDefinition.php index 47a7653..1bc31fc 100644 --- a/Civi/Api4/ContactCategoryDefinition.php +++ b/Civi/Api4/ContactCategoryDefinition.php @@ -1,6 +1,8 @@ setCheckPermissions($checkPermissions); + } + } diff --git a/ang/crmContactcats.js b/ang/crmContactcats.js index e9fd138..0405af0 100644 --- a/ang/crmContactcats.js +++ b/ang/crmContactcats.js @@ -22,133 +22,75 @@ // this.$onInit gets run after the this controller is called, and after the bindings have been applied. this.$onInit = async function() { ctrl.saved = false; - const various = await crmApi4({ - settings: ["Setting", "get", { select: ["contact_categories"] }, 0], - groups: [ - "Group", - "get", - { - where: [ - ["is_active", "=", 1], - ["is_hidden", "=", 0] - ], - orderBy: { name: "ASC" } - } - ], - cats: [ - "OptionValue", - "get", - { - select: ["value", "label"], - where: [["option_group_id:name", "=", "contact_categories"]] - } - ] - }); - ctrl.catmap = []; - if (!various.settings.value || !various.settings.value.groupIDs) { - various.settings.value = { - groupIDs: ["0"], - updateAfter: 0 - }; - } - various.settings.value.groupIDs.forEach(groupID => { - let cat = various.cats.find(c => c.value == groupID); - ctrl.catmap.push({ - groupID, - name: cat ? cat.label : "" - }); - }); - console.log({ various, catmap: ctrl.catmap }); - ctrl.groups = various.groups; - ctrl.nameKeydown = (keyEvt, idx) => { - if (keyEvt.key === "ArrowUp" || keyEvt.key === "ArrowDown") { - keyEvt.preventDefault(); - keyEvt.stopPropagation(); - if ( - keyEvt.key === "ArrowUp" && - idx > 0 && - idx < ctrl.catmap.length - 1 - ) { - ctrl.catmap.splice(idx, 0, ...ctrl.catmap.splice(idx - 1, 1)); - console.log("up", { keyEvt }); - $timeout(() => keyEvt.target.focus(), 10); - } else if ( - keyEvt.key === "ArrowDown" && - idx < ctrl.catmap.length - 2 - ) { - ctrl.catmap.splice(idx + 1, 0, ...ctrl.catmap.splice(idx, 1)); - console.log( - "down", - ctrl.catmap.map(e => e.name) - ); - } - } - }; + ctrl.categoryDefinitions = null; + ctrl.categoryDefinitions = await crmApi4("ContactCategoryDefinition", 'get', { orderBy: { label: 'ASC' }, withLabels: true }); + $scope.$digest(); - ctrl.deleteRow = idx => { - ctrl.catmap.splice(idx, 1); - }; - ctrl.getGroupsFor = idx => { - let groupsInUse = ctrl.catmap.map(c => c.groupID); - groupsInUse.splice(idx, 1); - return ctrl.groups.filter( - g => !groupsInUse.includes(g.id.toString()) - ); - }; - ctrl.save = async () => { - console.log("save", ctrl.catmap); - // reconstruct everything. + // ctrl.deleteRow = idx => { + // ctrl.catmap.splice(idx, 1); + // }; + // ctrl.getGroupsFor = idx => { + // let groupsInUse = ctrl.catmap.map(c => c.groupID); + // groupsInUse.splice(idx, 1); + // return ctrl.groups.filter( + // g => !groupsInUse.includes(g.id.toString()) + // ); + // }; - const optValsRecords = []; - ctrl.catmap.forEach(r => { - if (!r.name || r.groupID === "") { - return; - } - // Do we have an option value for this group ID? - let c = various.cats.find(cat => cat.value == r.groupID); - if (c) { - if (c.label != r.name) { - optValsRecords.push({ - id: c.id, - label: r.name - }); - } - } else { - optValsRecords.push({ - label: r.name, - value: r.groupID, - "option_group_id:name": "contact_categories" - }); - } - }); - console.log("optionValue updates", optValsRecords, ctrl.catmap); - const updates = { - saveSetting: [ - "Setting", - "set", - { - values: { - contact_categories: { - groupIDs: ctrl.catmap.map(i => i.groupID), - updateAfter: 0 - } - } - } - ] - }; - if (optValsRecords.length) { - updates.saveOptions = [ - "OptionValue", - "save", - { records: optValsRecords } - ]; - } - await crmApi4(updates); - console.log("saved", updates); - ctrl.saved = true; - $scope.$digest(); - }; + // ctrl.save = async () => { + // console.log("save", ctrl.catmap); + // // reconstruct everything. + // + // const optValsRecords = []; + // ctrl.catmap.forEach(r => { + // if (!r.name || r.groupID === "") { + // return; + // } + // // Do we have an option value for this group ID? + // let c = various.cats.find(cat => cat.value == r.groupID); + // if (c) { + // if (c.label != r.name) { + // optValsRecords.push({ + // id: c.id, + // label: r.name + // }); + // } + // } else { + // optValsRecords.push({ + // label: r.name, + // value: r.groupID, + // "option_group_id:name": "contact_categories" + // }); + // } + // }); + // console.log("optionValue updates", optValsRecords, ctrl.catmap); + // const updates = { + // saveSetting: [ + // "Setting", + // "set", + // { + // values: { + // contact_categories: { + // groupIDs: ctrl.catmap.map(i => i.groupID), + // updateAfter: 0 + // } + // } + // } + // ] + // }; + // if (optValsRecords.length) { + // updates.saveOptions = [ + // "OptionValue", + // "save", + // { records: optValsRecords } + // ]; + // } + // await crmApi4(updates); + // console.log("saved", updates); + // ctrl.saved = true; + // $scope.$digest(); + // }; }; // this.$onChange = function(changes) { // // changes is object keyed by name what '<' binding changed in diff --git a/ang/crmContactcats/crmContactCategorySettings.html b/ang/crmContactcats/crmContactCategorySettings.html index 6fd8380..70cc933 100644 --- a/ang/crmContactcats/crmContactCategorySettings.html +++ b/ang/crmContactcats/crmContactCategorySettings.html @@ -1,51 +1,34 @@ -
+
Loading...
-
+ + + + +
    -
  1. -
    - -
    -
    - Default -
    -
    - - -
    - {{ts('Use the Up/Down arrow keys to re-order')}} -
    -
    -
    +
  2. + + + + {{row.label}} + + + -
+ +

diff --git a/schema/ContactCategory.entityType.php b/schema/ContactCategory.entityType.php index b3c213f..fc9dadd 100644 --- a/schema/ContactCategory.entityType.php +++ b/schema/ContactCategory.entityType.php @@ -12,9 +12,9 @@ return [ 'log' => FALSE, ], 'getIndices' => fn() => [ - 'index_category' => [ + 'index_category_definition_id' => [ 'fields' => [ - 'category' => TRUE, + 'category_definition_id' => TRUE, ], ], ], @@ -43,25 +43,24 @@ return [ 'on_delete' => 'CASCADE', ], ], - 'category' => [ - 'title' => E::ts('Category'), + 'category_definition_id' => [ + 'title' => E::ts('Category Definition'), 'sql_type' => 'int unsigned', - 'input_type' => 'Select', 'required' => TRUE, 'default' => 0, - 'pseudoconstant' => [ - 'option_group_name' => 'contact_categories', + 'input_type' => 'EntityRef', + 'entity_reference' => [ + 'entity' => 'ContactCategoryDefinition', + 'key' => 'id', + 'on_delete' => 'CASCADE', ], ], 'next_category' => [ 'title' => E::ts('Next Category'), 'sql_type' => 'int unsigned', - 'input_type' => 'Select', 'required' => TRUE, 'default' => 0, - 'pseudoconstant' => [ - 'option_group_name' => 'contact_categories', - ], + 'input_type' => 'Hidden', /* not needed to be exposed */ ], ], ]; diff --git a/schema/ContactCategoryDescription.entityType.php b/schema/ContactCategoryDefinition.entityType.php similarity index 75% rename from schema/ContactCategoryDescription.entityType.php rename to schema/ContactCategoryDefinition.entityType.php index 1d01ef8..25ca278 100644 --- a/schema/ContactCategoryDescription.entityType.php +++ b/schema/ContactCategoryDefinition.entityType.php @@ -2,29 +2,22 @@ use CRM_Contactcats_ExtensionUtil as E; return [ - 'name' => 'ContactCategoryDescription', - 'table' => 'civicrm_contact_category_description', - 'class' => 'CRM_Contactcats_DAO_ContactCategoryDescription', + 'name' => 'ContactCategoryDefinition', + 'table' => 'civicrm_contact_category_definition', + 'class' => 'CRM_Contactcats_DAO_ContactCategoryDefinition', 'getInfo' => fn() => [ - 'title' => E::ts('Contact Category Description'), - 'title_plural' => E::ts('Contact Category Descriptions'), + 'title' => E::ts('Contact Category Definition'), + 'title_plural' => E::ts('Contact Category Definitions'), 'description' => E::ts('Holds definition of a "Contact category"'), 'log' => FALSE, ], - 'getIndices' => fn() => [ - 'index_category' => [ - 'fields' => [ - 'category' => TRUE, - ], - ], - ], 'getFields' => fn() => [ 'id' => [ 'title' => E::ts('ID'), 'sql_type' => 'int unsigned', 'input_type' => 'Number', 'required' => TRUE, - 'description' => E::ts('Unique Contact Category Description ID'), + 'description' => E::ts('Unique Contact Category Definition ID'), 'primary_key' => TRUE, 'auto_increment' => TRUE, ], @@ -33,14 +26,13 @@ return [ 'sql_type' => 'varchar(255)', 'input_type' => 'Text', 'required' => TRUE, - 'description' => E::ts('Same as id but for FormBuilder'), 'input_attrs' => [ 'text_length' => 255, 'label' => E::ts('Category name'), ], ], 'search_type' => [ - 'title' => E::ts('What defines this search?'), + 'title' => E::ts('Definition type'), 'sql_type' => 'varchar(12)', 'input_type' => 'Select', 'required' => TRUE, @@ -59,11 +51,12 @@ return [ 'title' => E::ts('JSON blob specifies particulars to for the search_type'), 'description' => E::ts('Holds data specific to the search specification (e.g. a group ID when Group is selected).'), 'sql_type' => 'text', - 'serialize' => 'JSON', + 'serialize' => CRM_Core_DAO::SERIALIZE_JSON, ], 'color' => [ 'title' => E::ts('Colour for category label'), 'sql_type' => 'varchar(7)', + 'input_type' => 'Color', 'default' => '', 'required' => TRUE, ], @@ -77,7 +70,7 @@ return [ 'execution_order' => [ 'title' => E::ts('Execution order'), 'description' => E::ts('The first category to match is assigned. Lower numbers are tested first.'), - 'sql_type' => 'tinyint unsigned', + 'sql_type' => 'int(1) unsigned', 'default' => '10', 'required' => TRUE, ],