CRM-15801 - crmMailing - Special formatting for recipients based on searches.
authorTim Otten <totten@civicrm.org>
Fri, 20 Feb 2015 03:50:31 +0000 (19:50 -0800)
committerTim Otten <totten@civicrm.org>
Fri, 20 Feb 2015 03:50:31 +0000 (19:50 -0800)
css/angular-crmMailing.css
js/angular-crmMailing/directives.js
partials/crmMailing/directive/recipients.html
partials/crmMailing/recipients.html

index d5536a58e2bc5515de706129b73a8ddfaed16e3d..dd24aec8dbaf0a02ef3fde3d775fcd69afa45968 100644 (file)
@@ -26,6 +26,9 @@ span.crmMailing-exclude {
   color: #600;
   text-decoration: line-through;
 }
+span.crmMailing-mandatory {
+  color: #866304;
+}
 
 .crmMailing input[name=preview_test_email], .crmMailing-preview select[name=preview_test_group] {
   width: 80%;
index 4767e3ccfc5201b4f7a9fe21462bbffc00b54974..340ea4a8686ae361a79de20646c5daf1d89c94d9 100644 (file)
 
   // example: <select multiple crm-mailing-recipients crm-mailing="mymailing" crm-avail-groups="myGroups" crm-avail-mailings="myMailings"></select>
   // FIXME: participate in ngModel's validation cycle
-  angular.module('crmMailing').directive('crmMailingRecipients', function () {
+  angular.module('crmMailing').directive('crmMailingRecipients', function (crmUiAlert) {
     return {
       restrict: 'AE',
       require: 'ngModel',
       scope: {
         crmAvailGroups: '@', // available groups
         crmAvailMailings: '@', // available mailings
+        crmMandatoryGroups: '@', // hard-coded/mandatory groups
         ngRequired: '@'
       },
       templateUrl: '~/crmMailing/directive/recipients.html',
         scope.recips = ngModel.$viewValue;
         scope.groups = scope.$parent.$eval(attrs.crmAvailGroups);
         scope.mailings = scope.$parent.$eval(attrs.crmAvailMailings);
+        refreshMandatory();
 
-        scope.ts = CRM.ts(null);
+        var ts = scope.ts = CRM.ts(null);
 
         /// Convert MySQL date ("yyyy-mm-dd hh:mm:ss") to JS date object
         scope.parseDate = function (date) {
           return r;
         }
 
+        function refreshMandatory() {
+          if (ngModel.$viewValue.groups) {
+            scope.mandatoryGroups = _.filter(scope.$parent.$eval(attrs.crmMandatoryGroups), function(grp) {
+              return _.contains(ngModel.$viewValue.groups.include, parseInt(grp.id));
+            });
+            scope.mandatoryIds = _.map(_.pluck(scope.$parent.$eval(attrs.crmMandatoryGroups), 'id'), function(n) {
+              return parseInt(n);
+            });
+          }
+          else {
+            scope.mandatoryGroups = [];
+            scope.mandatoryIds = [];
+          }
+        }
+
+        function isMandatory(grpId) {
+          return _.contains(scope.mandatoryIds, parseInt(grpId));
+        }
+
         var refreshUI = ngModel.$render = function refresuhUI() {
           scope.recips = ngModel.$viewValue;
           if (ngModel.$viewValue) {
             $(element).select2('val', convertMailingToValues(ngModel.$viewValue));
             validate();
+            refreshMandatory();
           }
         };
 
           var option = convertValueToObj(item.id);
           var icon = (option.entity_type === 'civicrm_mailing') ? 'EnvelopeIn.gif' : 'group.png';
           var spanClass = (option.mode == 'exclude') ? 'crmMailing-exclude' : 'crmMailing-include';
+          if (option.entity_type != 'civicrm_mailing' && isMandatory(option.entity_id)) {
+            spanClass = 'crmMailing-mandatory';
+          }
           return "<img src='../../sites/all/modules/civicrm/i/" + icon + "' height=12 width=12 /> <span class='" + spanClass + "'>" + item.text + "</span>";
         }
 
         $(element).on("select2-removing", function (e) {
           var option = convertValueToObj(e.val);
           var typeKey = option.entity_type == 'civicrm_mailing' ? 'mailings' : 'groups';
+          if (typeKey == 'groups' && isMandatory(option.entity_id)) {
+            crmUiAlert({
+              text: ts('This mailing was generated based on search results. The search results cannot be removed.'),
+              title: ts('Required')
+            });
+            e.preventDefault();
+            return;
+          }
           scope.$parent.$apply(function () {
             arrayRemove(ngModel.$viewValue[typeKey][option.mode], option.entity_id);
           });
         scope.$watchCollection("recips.mailings.exclude", refreshUI);
         setTimeout(refreshUI, 50);
 
-        scope.$watchCollection(attrs.crmAvailGroups, function(){
+        scope.$watchCollection(attrs.crmAvailGroups, function() {
           scope.groups = scope.$parent.$eval(attrs.crmAvailGroups);
         });
-        scope.$watchCollection(attrs.crmAvailMailings, function(){
+        scope.$watchCollection(attrs.crmAvailMailings, function() {
           scope.mailings = scope.$parent.$eval(attrs.crmAvailMailings);
         });
+        scope.$watchCollection(attrs.crmMandatoryGroups, function() {
+          refreshMandatory();
+        });
       }
     };
   });
index bc12d7ae06e6800d880503d556282668b2bb8a2b..9d84e93931bdc9c89aee9b36c77ddf82149363ca 100644 (file)
@@ -2,6 +2,9 @@
 Directive: crmMailingRecipients
 -->
 <select multiple>
+  <optgroup label="{{ts('Mandatory Group')}}">
+    <option ng-repeat="grp in mandatoryGroups" value="{{grp.id}} civicrm_group include">{{ts('Search Results')}}</option>
+  </optgroup>
   <optgroup label="{{ts('Include Group')}}">
     <option ng-repeat="grp in groups" value="{{grp.id}} civicrm_group include">{{grp.title}}</option>
   </optgroup>
index 905a27bd674a32b86096349f9c7a19ef0ab434d7..8c1f143dd790c413ffc12e7f2570924398db4da3 100644 (file)
@@ -7,6 +7,7 @@
   <select
     crm-mailing-recipients
     ng-model="mailing.recipients"
+    crm-mandatory-groups="crmMailingConst.groupNames | filter:{is_hidden:1}"
     crm-avail-groups="crmMailingConst.groupNames | filter:{visibility:'Public pages'}"
     crm-avail-mailings="crmMailingConst.civiMails | filter:{is_completed:1}"
     crm-ui-id="{{crmMailingBlockRecipients.id}}"