CRM-15856 - crmMailingRecipients - Use ngModel. Merge mailing.groups and mailing...
authorTim Otten <totten@civicrm.org>
Wed, 11 Feb 2015 21:47:54 +0000 (13:47 -0800)
committerTim Otten <totten@civicrm.org>
Thu, 12 Feb 2015 19:59:17 +0000 (11:59 -0800)
js/angular-crmMailing.js
js/angular-crmMailing/directives.js
js/angular-crmMailing/services.js
js/angular-crmMailingAB.js
partials/crmMailing/recipients.html

index 889f8af88a8e8d12d64f3170d73fc7ec4291cda5..ed5321d7b08a27c7621e8a36842577fb09d1ac6f 100644 (file)
     $scope.getIncludesAsString = function () {
       var first = true;
       var names = '';
-      _.each($scope.mailing.groups.include, function (id) {
+      _.each($scope.mailing.recipients.groups.include, function (id) {
         if (!first) {
           names = names + ', ';
         }
         names = names + group[0].title;
         first = false;
       });
-      _.each($scope.mailing.mailings.include, function (id) {
+      _.each($scope.mailing.recipients.mailings.include, function (id) {
         if (!first) {
           names = names + ', ';
         }
     $scope.getExcludesAsString = function () {
       var first = true;
       var names = '';
-      _.each($scope.mailing.groups.exclude, function (id) {
+      _.each($scope.mailing.recipients.groups.exclude, function (id) {
         if (!first) {
           names = names + ', ';
         }
         names = names + group[0].title;
         first = false;
       });
-      _.each($scope.mailing.mailings.exclude, function (id) {
+      _.each($scope.mailing.recipients.mailings.exclude, function (id) {
         if (!first) {
           names = names + ', ';
         }
         });
       });
     }, RECIPIENTS_DEBOUNCE_MS);
-    $scope.$watchCollection("mailing.groups.include", refreshRecipients);
-    $scope.$watchCollection("mailing.groups.exclude", refreshRecipients);
-    $scope.$watchCollection("mailing.mailings.include", refreshRecipients);
-    $scope.$watchCollection("mailing.mailings.exclude", refreshRecipients);
+    $scope.$watchCollection("mailing.recipients.groups.include", refreshRecipients);
+    $scope.$watchCollection("mailing.recipients.groups.exclude", refreshRecipients);
+    $scope.$watchCollection("mailing.recipients.mailings.include", refreshRecipients);
+    $scope.$watchCollection("mailing.recipients.mailings.exclude", refreshRecipients);
 
     $scope.previewRecipients = function previewRecipients() {
       var model = {
index dd80fa324db7e86e78eda748a1a2a1dc0bad4727..d86fed8cfaae560e4d1e0cc89fa3eaa267aed1ea 100644 (file)
   angular.module('crmMailing').directive('crmMailingRecipients', function () {
     return {
       restrict: 'AE',
+      require: 'ngModel',
       scope: {
         crmAvailGroups: '@', // available groups
         crmAvailMailings: '@', // available mailings
-        crmMailing: '@' // the mailing for which we are choosing recipients
       },
       templateUrl: '~/crmMailing/directive/recipients.html',
-      link: function (scope, element, attrs) {
-        scope.mailing = scope.$parent.$eval(attrs.crmMailing);
+      link: function (scope, element, attrs, ngModel) {
+        scope.recips = ngModel.$viewValue;
         scope.groups = scope.$parent.$eval(attrs.crmAvailGroups);
         scope.mailings = scope.$parent.$eval(attrs.crmAvailMailings);
 
 
         // @param Object mailing
         // @return array list of values like "4 civicrm_mailing include"
-        function convertMailingToValues(mailing) {
+        function convertMailingToValues(recipients) {
           var r = [];
-          angular.forEach(mailing.groups.include, function (v) {
+          angular.forEach(recipients.groups.include, function (v) {
             r.push(v + " civicrm_group include");
           });
-          angular.forEach(mailing.groups.exclude, function (v) {
+          angular.forEach(recipients.groups.exclude, function (v) {
             r.push(v + " civicrm_group exclude");
           });
-          angular.forEach(mailing.mailings.include, function (v) {
+          angular.forEach(recipients.mailings.include, function (v) {
             r.push(v + " civicrm_mailing include");
           });
-          angular.forEach(mailing.mailings.exclude, function (v) {
+          angular.forEach(recipients.mailings.exclude, function (v) {
             r.push(v + " civicrm_mailing exclude");
           });
           return r;
         }
 
-        // Update $(element) view based on latest data
-        function refreshUI() {
-          if (scope.mailing) {
-            $(element).select2('val', convertMailingToValues(scope.mailing));
+        var refreshUI = ngModel.$render = function refresuhUI() {
+          scope.recips = ngModel.$viewValue;
+          if (ngModel.$viewValue) {
+            $(element).select2('val', convertMailingToValues(ngModel.$viewValue));
           }
-        }
+        };
 
         /// @return string HTML representingn an option
         function formatItem(item) {
           var option = convertValueToObj(e.val);
           var typeKey = option.entity_type == 'civicrm_mailing' ? 'mailings' : 'groups';
           if (option.mode == 'exclude') {
-            scope.mailing[typeKey].exclude.push(option.entity_id);
-            arrayRemove(scope.mailing[typeKey].include, option.entity_id);
+            ngModel.$viewValue[typeKey].exclude.push(option.entity_id);
+            arrayRemove(ngModel.$viewValue[typeKey].include, option.entity_id);
           }
           else {
-            scope.mailing[typeKey].include.push(option.entity_id);
-            arrayRemove(scope.mailing[typeKey].exclude, option.entity_id);
+            ngModel.$viewValue[typeKey].include.push(option.entity_id);
+            arrayRemove(ngModel.$viewValue[typeKey].exclude, option.entity_id);
           }
           scope.$apply();
           $(element).select2('close');
           var option = convertValueToObj(e.val);
           var typeKey = option.entity_type == 'civicrm_mailing' ? 'mailings' : 'groups';
           scope.$parent.$apply(function () {
-            arrayRemove(scope.mailing[typeKey][option.mode], option.entity_id);
+            arrayRemove(ngModel.$viewValue[typeKey][option.mode], option.entity_id);
           });
           e.preventDefault();
         });
 
-        scope.$watchCollection(attrs.crmMailing + ".groups.include", refreshUI);
-        scope.$watchCollection(attrs.crmMailing + ".groups.exclude", refreshUI);
-        scope.$watchCollection(attrs.crmMailing + ".mailings.include", refreshUI);
-        scope.$watchCollection(attrs.crmMailing + ".mailings.exclude", refreshUI);
+        scope.$watchCollection("recips.groups.include", refreshUI);
+        scope.$watchCollection("recips.groups.exclude", refreshUI);
+        scope.$watchCollection("recips.mailings.include", refreshUI);
+        scope.$watchCollection("recips.mailings.exclude", refreshUI);
         setTimeout(refreshUI, 50);
 
-        scope.$watch(attrs.crmMailing, function(){
-          scope.mailing = scope.$parent.$eval(attrs.crmMailing);
-        });
         scope.$watchCollection(attrs.crmAvailGroups, function(){
           scope.groups = scope.$parent.$eval(attrs.crmAvailGroups);
         });
index 65861b2c8a7f3a7026fd9b8b552607546dbe48b2..01b04d3287b5c71d5c9f1c7f4ff980b0a5e8410d 100644 (file)
       _loadGroups: function (mailing) {
         return crmApi('MailingGroup', 'get', {mailing_id: mailing.id})
           .then(function (groupResult) {
-            mailing.groups = {include: [], exclude: []};
-            mailing.mailings = {include: [], exclude: []};
+            mailing.recipients = {};
+            mailing.recipients.groups = {include: [], exclude: []};
+            mailing.recipients.mailings = {include: [], exclude: []};
             _.each(groupResult.values, function (mailingGroup) {
               var bucket = (/^civicrm_group/.test(mailingGroup.entity_table)) ? 'groups' : 'mailings';
               var entityId = parseInt(mailingGroup.entity_id);
-              mailing[bucket][mailingGroup.group_type.toLowerCase()].push(entityId);
+              mailing.recipients[bucket][mailingGroup.group_type.toLowerCase()].push(entityId);
             });
           });
       },
       create: function create(params) {
         var defaults = {
           jobs: {}, // {jobId: JobRecord}
-          groups: {include: [], exclude: []},
-          mailings: {include: [], exclude: []},
+          recipients: {
+            groups: {include: [], exclude: []},
+            mailings: {include: [], exclude: []},
+          },
           name: "",
           campaign_id: null,
           replyto_email: "",
           'replyto_email',
           'subject',
           'dedupe_email',
-          'groups',
-          'mailings',
+          'recipients',
           'body_html',
           'body_text',
           'footer_id',
       // @param mailing Object (per APIv3)
       // @return Promise an object with "subject", "body_text", "body_html"
       preview: function preview(mailing) {
-        var params = angular.extend({}, mailing, {
+        var params = angular.extend({}, mailing, mailing.recipients, {
           options: {force_rollback: 1},
           'api.Mailing.preview': {
             id: '$value.id'
           }
         });
+        delete params.recipients; // the content was merged in
         return crmApi('Mailing', 'create', params).then(function (result) {
           // changes rolled back, so we don't care about updating mailing
           return result.values[result.id]['api.Mailing.preview'].values;
       previewRecipients: function previewRecipients(mailing, previewLimit) {
         // To get list of recipients, we tentatively save the mailing and
         // get the resulting recipients -- then rollback any changes.
-        var params = angular.extend({}, mailing, {
+        var params = angular.extend({}, mailing, mailing.recipients, {
           name: 'placeholder', // for previewing recipients on new, incomplete mailing
           subject: 'placeholder', // for previewing recipients on new, incomplete mailing
           options: {force_rollback: 1},
             'api.email.getvalue': {'return': 'email'}
           }
         });
+        delete params.recipients; // the content was merged in
         return crmApi('Mailing', 'create', params).then(function (recipResult) {
           // changes rolled back, so we don't care about updating mailing
           return recipResult.values[recipResult.id]['api.MailingRecipients.get'].values;
       // @param mailing Object (per APIv3)
       // @return Promise
       save: function(mailing) {
-        var params = angular.extend({}, mailing);
+        var params = angular.extend({}, mailing, mailing.recipients);
 
         // Angular ngModel sometimes treats blank fields as undefined.
         angular.forEach(mailing, function(value, key) {
 
         delete params.jobs;
 
+        delete params.recipients; // the content was merged in
+
         return crmApi('Mailing', 'create', params).then(function(result) {
           if (result.id && !mailing.id) {
             mailing.id = result.id;
       // @param to Object with either key "email" (string) or "gid" (int)
       // @return Promise for a list of delivery reports
       sendTest: function (mailing, recipient) {
-        var params = angular.extend({}, mailing, {
+        var params = angular.extend({}, mailing, mailing.recipients, {
           // options:  {force_rollback: 1}, // Test mailings include tracking features, so the mailing must be persistent
           'api.Mailing.send_test': {
             mailing_id: '$value.id',
 
         delete params.jobs;
 
+        delete params.recipients; // the content was merged in
+
         return crmApi('Mailing', 'create', params).then(function (result) {
           if (result.id && !mailing.id) {
             mailing.id = result.id;
index 279fb1210036599c780af6849e33cca7f93b55fb..657c8c23620c4a3ff4a74ca919eca75c290b605c 100644 (file)
           case 'Subject lines':
             crmMailingMgr.mergeInto(abtest.mailings.b, abtest.mailings.a, [
               'name',
-              'groups',
-              'mailings',
+              'recipients',
               'subject'
             ]);
             break;
           case 'From names':
             crmMailingMgr.mergeInto(abtest.mailings.b, abtest.mailings.a, [
               'name',
-              'groups',
-              'mailings',
+              'recipients',
               'from_name',
               'from_email'
             ]);
           case 'Two different emails':
             crmMailingMgr.mergeInto(abtest.mailings.b, abtest.mailings.a, [
               'name',
-              'groups',
-              'mailings',
+              'recipients',
               'subject',
               'from_name',
               'from_email',
       buttons[ts('Select Winner')] = function () {
         crmMailingMgr.mergeInto(abtest.mailings.c, abtest.mailings[mailingName], [
           'name',
-          'groups',
-          'mailings',
+          'recipients',
           'scheduled_date'
         ]);
         crmStatus({start: ts('Saving...'), success: ''}, abtest.save())
index f2855528377a0cf7ebdc2e47b384f4a1caae1dbc..3306ef4aea2bac5c5926b3b69b102a0e81f80ed0 100644 (file)
@@ -17,7 +17,7 @@
   </div>
   <select
     crm-mailing-recipients
-    crm-mailing="mailing"
+    ng-model="mailing.recipients"
     crm-avail-groups="crmMailingConst.groupNames | filter:{visibility:'Public pages'}"
     crm-avail-mailings="crmMailingConst.civiMails | filter:{is_completed:1}"
     crm-ui-id="{{crmMailingBlockRecipients.id}}"