(function(angular, $, _) { // Declare a list of dependencies. angular.module('crmContactcats', CRM.angRequires('crmContactcats')); angular.module('crmContactcats').component('crmContactCategorySettings', { templateUrl: '~/crmContactcats/crmContactCategorySettings.html', bindings: { // things listed here become properties on the controller using // values from attributes. @ means a fixed string is passed // e.g. // token: '@', // & is special. In the child, call ctrl.onMyAction with an // Object whose keys provide parameter names for the code in the parent. // onMyAction: '&', // '<' means one-way binding (parent»child) and I think is what you are // supposed to use for components. // v: '<' }, controller: function($scope, $timeout, crmApi4, $document) { var ts = $scope.ts = CRM.ts(null), ctrl = this; // 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)); } } }; $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"); // reconstruct everything. const optValsRecords = []; let isInvalid = false; 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 // // the parent (e.g. 'v'), and value is another obj with keys // // something like previous, new, ...?... // }; } }); })(angular, CRM.$, CRM._);