From 7a646a012944ef1722d56c28eb0169aed7bc4ec6 Mon Sep 17 00:00:00 2001 From: "deb.monish" <monish.deb@jmaconsulting.biz> Date: Mon, 9 Oct 2017 19:50:15 +0530 Subject: [PATCH] Rebuild recipient list and calculate count on demand, store result in --- ang/crmMailing.css | 10 +++++ ang/crmMailing/BlockRecipients.html | 17 +++++--- ang/crmMailing/EditRecipCtrl.js | 66 +++++++++++++++++++---------- ang/crmMailing/services.js | 60 ++++++++++++++++++-------- 4 files changed, 107 insertions(+), 46 deletions(-) diff --git a/ang/crmMailing.css b/ang/crmMailing.css index b853cb4466e3..3c39b693128a 100644 --- a/ang/crmMailing.css +++ b/ang/crmMailing.css @@ -111,3 +111,13 @@ input[name=preview_test_email]:-ms-input-placeholder { margin: 0.5em; color: red; } + +.crmMailing-outdated-count { + color: red; + font-weight: bold; +} + +.crmMailing-latest-count { + color: green; + font-weight: bold; +} diff --git a/ang/crmMailing/BlockRecipients.html b/ang/crmMailing/BlockRecipients.html index 83af7a574198..d205f478f22c 100644 --- a/ang/crmMailing/BlockRecipients.html +++ b/ang/crmMailing/BlockRecipients.html @@ -1,9 +1,4 @@ <div ng-controller="EditRecipCtrl" class="crm-mailing-recipients-row"> - <div style="float: right;"> - <div class="crmMailing-recip-est"> - <a href="" ng-click="previewRecipients()" title="{{ts('Preview a List of Recipients')}}">{{getRecipientsEstimate()}}</a> - </div> - </div> <input type="hidden" crm-mailing-recipients @@ -11,6 +6,14 @@ crm-mandatory-groups="crmMailingConst.groupNames | filter:{is_hidden:1}" crm-ui-id="{{crmMailingBlockRecipients.id}}" name="{{crmMailingBlockRecipients.name}}" - ng-required="true"/> - <a crm-icon="fa-wrench" ng-click="editOptions(mailing)" class="crm-hover-button" title="{{ts('Edit Recipient Options')}}"></a> + ng-required="true" /> + <a crm-icon="fa-wrench" ng-click="editOptions(mailing)" class="crm-hover-button" title="{{ts('Edit Recipient Options')}}"></a> + <div> + <button ng-click="rebuildRecipients()" class="ng-binding crm-button" title="{{ts('Preview a List of Recipients')}}">{{getRecipientsEstimate()}}</button> + <a ng-click="previewRecipients()" class="crm-hover-button" title="{{ts('Click to refresh recipient count')}}"> + <span class="{{((outdated || recipient == 0) ? 'crmMailing-outdated-count' : 'crmMailing-latest-count')}}"> + {{getRecipientCount()}} + </span> + </a> + </div> </div> diff --git a/ang/crmMailing/EditRecipCtrl.js b/ang/crmMailing/EditRecipCtrl.js index 16c125f8cfca..3064384065eb 100644 --- a/ang/crmMailing/EditRecipCtrl.js +++ b/ang/crmMailing/EditRecipCtrl.js @@ -5,7 +5,7 @@ // Scope members: // - [input] mailing: object // - [output] recipients: array of recipient records - angular.module('crmMailing').controller('EditRecipCtrl', function EditRecipCtrl($scope, dialogService, crmApi, crmMailingMgr, $q, crmMetadata, crmStatus) { + angular.module('crmMailing').controller('EditRecipCtrl', function EditRecipCtrl($scope, dialogService, crmApi, crmMailingMgr, $q, crmMetadata, crmStatus, crmMailingCache) { // Time to wait before triggering AJAX update to recipients list var RECIPIENTS_DEBOUNCE_MS = 100; var RECIPIENTS_PREVIEW_LIMIT = 50; @@ -18,29 +18,36 @@ }; $scope.recipients = null; + $scope.outdated = null; + $scope.getRecipientsEstimate = function() { var ts = $scope.ts; if ($scope.recipients === null) { return ts('(Estimating)'); } if ($scope.recipients === 0) { - return ts('No recipients'); + return ts('Estimate recipient count'); } - if ($scope.recipients === 1) { - return ts('~1 recipient'); + return ts('Refresh recipient count'); + }; + + $scope.getRecipientCount = function() { + var ts = $scope.ts; + if ($scope.recipients === 0) { + return ts('(unknown)'); } - return ts('~%1 recipients', {1: $scope.recipients}); + return ($scope.recipients === 1) ? ts('~1 recipient') : ts('~%1 recipients', {1 : $scope.recipients}); }; // We monitor four fields -- use debounce so that changes across the // four fields can settle-down before AJAX. var refreshRecipients = _.debounce(function() { $scope.$apply(function() { - $scope.recipients = null; if (!$scope.mailing) { return; } - crmMailingMgr.previewRecipientCount($scope.mailing).then(function(recipients) { + crmMailingMgr.previewRecipientCount($scope.mailing, crmMailingCache, false).then(function(recipients) { + $scope.outdated = (_.difference($scope.mailing.recipients, crmMailingCache.get('mailing-' + $scope.mailing.id + '-recipient-params')) !== 0); $scope.recipients = recipients; }); }); @@ -54,21 +61,36 @@ $scope.$watchCollection("mailing.recipients.mailings.exclude", refreshRecipients); $scope.previewRecipients = function previewRecipients() { - return crmStatus({start: ts('Previewing...'), success: ''}, crmMailingMgr.previewRecipients($scope.mailing, RECIPIENTS_PREVIEW_LIMIT).then(function(recipients) { - var model = { - count: $scope.recipients, - sample: recipients, - sampleLimit: RECIPIENTS_PREVIEW_LIMIT - }; - var options = CRM.utils.adjustDialogDefaults({ - width: '40%', - autoOpen: false, - title: ts('Preview (%1)', { - 1: $scope.getRecipientsEstimate() - }) - }); - dialogService.open('recipDialog', '~/crmMailing/PreviewRecipCtrl.html', model, options); - })); + var model = { + count: $scope.recipients, + sample: crmMailingCache.get('mailing-' + $scope.mailing.id + '-recipient-list'), + sampleLimit: RECIPIENTS_PREVIEW_LIMIT + }; + var options = CRM.utils.adjustDialogDefaults({ + width: '40%', + autoOpen: false, + title: ts('Preview (%1)', {1: $scope.getRecipientCount()}) + }); + + // don't open preview dialog if there is no recipient to show. + if ($scope.recipients !== 0) { + if (!_.isEmpty(model.sample)) { + dialogService.open('recipDialog', '~/crmMailing/PreviewRecipCtrl.html', model, options); + } + else { + return crmStatus({start: ts('Previewing...'), success: ''}, crmMailingMgr.previewRecipients($scope.mailing, RECIPIENTS_PREVIEW_LIMIT).then(function(recipients) { + model.sample = recipients; + dialogService.open('recipDialog', '~/crmMailing/PreviewRecipCtrl.html', model, options); + })); + } + } + }; + + $scope.rebuildRecipients = function rebuildRecipients() { + return crmMailingMgr.previewRecipientCount($scope.mailing, crmMailingCache, true).then(function(recipients) { + $scope.outdated = (recipients === 0) ? true : false; + $scope.recipients = recipients; + }); }; // Open a dialog for editing the advanced recipient options. diff --git a/ang/crmMailing/services.js b/ang/crmMailing/services.js index 96d134070884..db9d2d9df816 100644 --- a/ang/crmMailing/services.js +++ b/ang/crmMailing/services.js @@ -310,24 +310,46 @@ }); }, - previewRecipientCount: function previewRecipientCount(mailing) { - // To get list of recipients, we tentatively save the mailing and - // get the resulting recipients -- then rollback any changes. - 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.mailing_job.create': 1, // note: exact match to API default - 'api.MailingRecipients.getcount': { - mailing_id: '$value.id' + previewRecipientCount: function previewRecipientCount(mailing, crmMailingCache, rebuild) { + var cachekey = 'mailing-' + mailing.id + '-recipient-count'; + var recipientCount = crmMailingCache.get(cachekey); + if (rebuild || _.isEmpty(recipientCount)) { + // To get list of recipients, we tentatively save the mailing and + // get the resulting recipients -- then rollback any changes. + 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.mailing_job.create': 1, // note: exact match to API default + 'api.MailingRecipients.getcount': { + mailing_id: '$value.id' + } + }); + // if this service is executed on rebuild then also fetch the recipients list + if (rebuild) { + params = angular.extend(params, { + 'api.MailingRecipients.get': { + mailing_id: '$value.id', + options: {limit: 50}, + 'api.contact.getvalue': {'return': 'display_name'}, + 'api.email.getvalue': {'return': 'email'} + } + }); + crmMailingCache.put('mailing-' + mailing.id + '-recipient-params', params.recipients); } - }); - delete params.recipients; // the content was merged in - return qApi('Mailing', 'create', params).then(function (recipResult) { - // changes rolled back, so we don't care about updating mailing - mailing.modified_date = recipResult.values[recipResult.id].modified_date; - return recipResult.values[recipResult.id]['api.MailingRecipients.getcount']; - }); + delete params.recipients; // the content was merged in + recipientCount = qApi('Mailing', 'create', params).then(function (recipResult) { + // changes rolled back, so we don't care about updating mailing + mailing.modified_date = recipResult.values[recipResult.id].modified_date; + if (rebuild) { + crmMailingCache.put('mailing-' + mailing.id + '-recipient-list', recipResult.values[recipResult.id]['api.MailingRecipients.get'].values); + } + return recipResult.values[recipResult.id]['api.MailingRecipients.getcount']; + }); + crmMailingCache.put(cachekey, recipientCount); + } + + return recipientCount; }, // Save a (draft) mailing @@ -555,4 +577,8 @@ }; }); + angular.module('crmMailing').factory('crmMailingCache', ['$cacheFactory', function($cacheFactory) { + return $cacheFactory('crmMailingCache'); + }]); + })(angular, CRM.$, CRM._);