From 58dfba8d4b6ad8a7f13672de86be9cd7b087f303 Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Thu, 18 Dec 2014 00:11:32 -0800 Subject: [PATCH] CRM-15578 - crmMailing - Fix for sending tests The basic problem is that one must save before sending a test -- and the "save" mechanics are necessarily different for crmMailing and crmMailingAB. This commit resolves the problem by refactoring to eliminate PreviewMailingCtrl. Now: * Ultimate authority for deciding how to perform a preview or test mailing lies with the main page (EditMailingCtrl, crmMailing/edit.html, CrmMailingABEditCtrl, crmMailingAB/edit.html) * We don't want it to be difficult for the main page to do that, so we define two reusable components -- directive crmMailingBlockPreview and service crmMailingPreviewMgr. --- js/angular-crmMailing.js | 85 +++++++------------------- js/angular-crmMailing/directives.js | 51 +++++++++++++++- js/angular-crmMailing/services.js | 56 +++++++++++++++-- js/angular-crmMailingAB.js | 18 +++++- partials/crmMailing/edit-unified.html | 2 +- partials/crmMailing/edit-unified2.html | 2 +- partials/crmMailing/edit-wizard.html | 2 +- partials/crmMailing/edit.html | 2 +- partials/crmMailing/preview.html | 15 +++-- partials/crmMailing/review.html | 8 +-- partials/crmMailingAB/edit.html | 8 +-- 11 files changed, 155 insertions(+), 94 deletions(-) diff --git a/js/angular-crmMailing.js b/js/angular-crmMailing.js index 6fd4987964..0f5b3bff03 100644 --- a/js/angular-crmMailing.js +++ b/js/angular-crmMailing.js @@ -66,7 +66,7 @@ }); }); - angular.module('crmMailing').controller('EditMailingCtrl', function EditMailingCtrl($scope, selectedMail, $location, crmMailingMgr, crmStatus, CrmAttachments) { + angular.module('crmMailing').controller('EditMailingCtrl', function EditMailingCtrl($scope, selectedMail, $location, crmMailingMgr, crmStatus, CrmAttachments, crmMailingPreviewMgr) { $scope.mailing = selectedMail; $scope.attachments = new CrmAttachments(function () { return {entity_table: 'civicrm_mailing', entity_id: $scope.mailing.id}; @@ -77,6 +77,23 @@ $scope.partialUrl = partialUrl; var ts = $scope.ts = CRM.ts('CiviMail'); + // @return Promise + $scope.previewMailing = function previewMailing(mailing, mode) { + return crmMailingPreviewMgr.preview(mailing, mode); + }; + + // @return Promise + $scope.sendTest = function sendTest(mailing, attachments, recipient) { + var savePromise = crmMailingMgr.save(mailing) + .then(function () { + return attachments.save(); + }); + return crmStatus({start: ts('Saving...'), success: ''}, savePromise) + .then(function () { + crmMailingPreviewMgr.sendTest(mailing, recipient); + }); + }; + // @return Promise $scope.submit = function submit() { var promise = crmMailingMgr.save($scope.mailing) @@ -89,6 +106,7 @@ }); return crmStatus({start: ts('Submitting...'), success: ts('Submitted')}, promise); }; + // @return Promise $scope.save = function save() { return crmStatus(null, @@ -100,12 +118,14 @@ }) ); }; + // @return Promise $scope.delete = function cancel() { return crmStatus({start: ts('Deleting...'), success: ts('Deleted')}, crmMailingMgr.delete($scope.mailing) ); }; + $scope.leave = function leave() { window.location = CRM.url('civicrm/mailing/browse/unscheduled', { reset: 1, @@ -229,67 +249,6 @@ $scope.ts = CRM.ts('CiviMail'); }); - // Controller for the "Preview Mailing" segment - // Note: Expects $scope.model to be an object with properties: - // - mailing: object - // - attachments: object - angular.module('crmMailing').controller('PreviewMailingCtrl', function ($scope, dialogService, crmMailingMgr, crmStatus) { - var ts = $scope.ts = CRM.ts('CiviMail'); - - $scope.testContact = {email: CRM.crmMailing.defaultTestEmail}; - $scope.testGroup = {gid: null}; - - $scope.previewHtml = function previewHtml() { - $scope.previewDialog(partialUrl('dialog/previewHtml.html')); - }; - $scope.previewText = function previewText() { - $scope.previewDialog(partialUrl('dialog/previewText.html')); - }; - $scope.previewFull = function previewFull() { - $scope.previewDialog(partialUrl('dialog/previewFull.html')); - }; - // Open a dialog with a preview of the current mailing - // @param template string URL of the template to use in the preview dialog - $scope.previewDialog = function previewDialog(template) { - var p = crmMailingMgr - .preview($scope.mailing) - .then(function (content) { - var options = { - autoOpen: false, - modal: true, - title: ts('Subject: %1', { - 1: content.subject - }) - }; - dialogService.open('previewDialog', template, content, options); - }); - CRM.status({start: ts('Previewing'), success: ''}, CRM.toJqPromise(p)); - }; - $scope.sendTestToContact = function sendTestToContact() { - $scope.sendTest($scope.mailing, $scope.attachments, $scope.testContact.email, null); - }; - $scope.sendTestToGroup = function sendTestToGroup() { - $scope.sendTest($scope.mailing, $scope.attachments, null, $scope.testGroup.gid); - }; - $scope.sendTest = function sendTest(mailing, attachments, testEmail, testGroup) { - var promise = crmMailingMgr.save(mailing) - .then(function () { - return attachments.save(); - }) - .then(function () { - return crmMailingMgr.sendTest(mailing, testEmail, testGroup); - }) - .then(function (deliveryInfos) { - var count = Object.keys(deliveryInfos).length; - if (count === 0) { - CRM.alert(ts('Could not identify any recipients. Perhaps the group is empty?')); - } - }) - ; - return crmStatus({start: ts('Sending...'), success: ts('Sent')}, promise); - }; - }); - // Controller for the "Preview Mailing" dialog // Note: Expects $scope.model to be an object with properties: // - "subject" @@ -441,7 +400,7 @@ setTimeout(scopeApply(init), 0); }); - angular.module('crmMailing').controller('EmailAddrCtrl', function EmailAddrCtrl($scope, crmFromAddresses){ + angular.module('crmMailing').controller('EmailAddrCtrl', function EmailAddrCtrl($scope, crmFromAddresses) { $scope.crmFromAddresses = crmFromAddresses; }); })(angular, CRM.$, CRM._); diff --git a/js/angular-crmMailing/directives.js b/js/angular-crmMailing/directives.js index bf1845fe20..53b24c41ca 100644 --- a/js/angular-crmMailing/directives.js +++ b/js/angular-crmMailing/directives.js @@ -8,11 +8,9 @@ var simpleBlocks = { crmMailingBlockHeaderFooter: partialUrl('headerFooter.html'), crmMailingBlockMailing: partialUrl('mailing.html'), - crmMailingBlockPreview: partialUrl('preview.html'), crmMailingBlockPublication: partialUrl('publication.html'), crmMailingBlockResponses: partialUrl('responses.html'), crmMailingBlockRecipients: partialUrl('recipients.html'), - crmMailingBlockReview: partialUrl('review.html'), crmMailingBlockSchedule: partialUrl('schedule.html'), crmMailingBlockSummary: partialUrl('summary.html'), crmMailingBlockTracking: partialUrl('tracking.html'), @@ -37,6 +35,51 @@ }); }); + // example:
+ // note: the directive defines a variable called "preview" with any inputs supplied by the user (e.g. the target recipient for an example mailing) + angular.module('crmMailing').directive('crmMailingBlockPreview', function ($parse) { + return { + templateUrl: partialUrl('preview.html'), + link: function (scope, elm, attr) { + var mailingModel = $parse(attr.crmMailing); + scope.mailing = mailingModel(scope); + scope.crmMailingConst = CRM.crmMailing; + scope.ts = CRM.ts('CiviMail'); + scope.testContact = {email: CRM.crmMailing.defaultTestEmail}; + scope.testGroup = {gid: null}; + + scope.doPreview = function(mode) { + scope.$eval(attr.onPreview, { + preview: {mode: mode} + }); + }; + scope.doSend = function doSend(recipient) { + scope.$eval(attr.onSend, { + preview: {recipient: recipient} + }); + }; + } + }; + }); + + angular.module('crmMailing').directive('crmMailingBlockReview', function ($parse, crmMailingPreviewMgr) { + return { + scope: { + crmMailing: '@' + }, + templateUrl: partialUrl('review.html'), + link: function (scope, elm, attr) { + var mailingModel = $parse(attr.crmMailing); + scope.mailing = mailingModel(scope.$parent); + scope.crmMailingConst = CRM.crmMailing; + scope.ts = CRM.ts('CiviMail'); + scope.previewMailing = function previewMailing(mailing, mode) { + return crmMailingPreviewMgr.preview(mailing, mode); + }; + } + }; + }); + // Convert between a mailing "From Address" (mailing.from_name,mailing.from_email) and a unified label ("Name" ) // example: // NOTE: This really doesn't belong in a directive. I've tried (and failed) to make this work with a getterSetter binding, eg @@ -247,7 +290,9 @@ // Update $(element) view based on latest data function refreshUI() { - $(element).select2('val', convertMailingToValues(scope.mailing)); + if (scope.mailing) { + $(element).select2('val', convertMailingToValues(scope.mailing)); + } } /// @return string HTML representingn an option diff --git a/js/angular-crmMailing/services.js b/js/angular-crmMailing/services.js index 7ecca99e55..3202ee054d 100644 --- a/js/angular-crmMailing/services.js +++ b/js/angular-crmMailing/services.js @@ -257,7 +257,7 @@ 'api.mailing_job.create': 1, // note: exact match to API default 'api.MailingRecipients.get': { mailing_id: '$value.id', - options: { limit: previewLimit }, + options: {limit: previewLimit}, 'api.contact.getvalue': {'return': 'display_name'}, 'api.email.getvalue': {'return': 'email'} } @@ -307,16 +307,15 @@ // Immediately send a test message // @param mailing Object (per APIv3) - // @param testEmail string - // @param testGroup int (id#) + // @param to Object with either key "email" (string) or "gid" (int) // @return Promise for a list of delivery reports - sendTest: function (mailing, testEmail, testGroup) { + sendTest: function (mailing, recipient) { var params = _.extend({}, mailing, { // options: {force_rollback: 1}, // Test mailings include tracking features, so the mailing must be persistent 'api.Mailing.send_test': { mailing_id: '$value.id', - test_email: testEmail, - test_group: testGroup + test_email: recipient.email, + test_group: recipient.gid } }); @@ -334,4 +333,49 @@ } }; }); + + // The preview manager performs preview actions while putting up a visible UI (e.g. dialogs & status alerts) + angular.module('crmMailing').factory('crmMailingPreviewMgr', function (dialogService, crmMailingMgr, crmStatus) { + return { + // @param mode string one of 'html', 'text', or 'full' + // @return Promise + preview: function preview(mailing, mode) { + var templates = { + html: partialUrl('dialog/previewHtml.html'), + text: partialUrl('dialog/previewText.html'), + full: partialUrl('dialog/previewFull.html') + }; + var result = null; + var p = crmMailingMgr + .preview(mailing) + .then(function (content) { + var options = { + autoOpen: false, + modal: true, + title: ts('Subject: %1', { + 1: content.subject + }) + }; + result = dialogService.open('previewDialog', templates[mode], content, options); + }); + crmStatus({start: ts('Previewing'), success: ''}, p); + return result; + }, + + // @param to Object with either key "email" (string) or "gid" (int) + // @return Promise + sendTest: function sendTest(mailing, recipient) { + var promise = crmMailingMgr.sendTest(mailing, recipient) + .then(function (deliveryInfos) { + var count = Object.keys(deliveryInfos).length; + if (count === 0) { + CRM.alert(ts('Could not identify any recipients. Perhaps the group is empty?')); + } + }) + ; + return crmStatus({start: ts('Sending...'), success: ts('Sent')}, promise); + } + }; + }); + })(angular, CRM.$, CRM._); diff --git a/js/angular-crmMailingAB.js b/js/angular-crmMailingAB.js index d4841feae3..47273b8d2b 100644 --- a/js/angular-crmMailingAB.js +++ b/js/angular-crmMailingAB.js @@ -38,10 +38,10 @@ $scope.testing_criteria = crmMailingABCriteria.getAll(); }); - angular.module('crmMailingAB').controller('CrmMailingABEditCtrl', function ($scope, abtest, crmMailingABCriteria, crmMailingMgr) { + angular.module('crmMailingAB').controller('CrmMailingABEditCtrl', function ($scope, abtest, crmMailingABCriteria, crmMailingMgr, crmMailingPreviewMgr, crmStatus) { window.ab = abtest; $scope.abtest = abtest; - $scope.ts = CRM.ts('CiviMail'); + var ts = $scope.ts = CRM.ts('CiviMail'); $scope.crmMailingABCriteria = crmMailingABCriteria; $scope.crmMailingConst = CRM.crmMailing; $scope.partialUrl = partialUrl; @@ -79,7 +79,19 @@ }; $scope.save = function save() { $scope.sync(); - return abtest.save(); + return crmStatus({start: ts('Saving...'), success: ts('Saved')}, abtest.save()); + }; + // @return Promise + $scope.previewMailing = function previewMailing(mailingName, mode) { + return crmMailingPreviewMgr.preview(abtest.mailings[mailingName], mode); + }; + + // @return Promise + $scope.sendTest = function sendTest(mailingName, recipient) { + return crmStatus({start: ts('Saving...'), success: ''}, abtest.save()) + .then(function () { + crmMailingPreviewMgr.sendTest(abtest.mailings[mailingName], recipient); + }); }; $scope.delete = function () { throw "Not implemented: EditCtrl.delete" diff --git a/partials/crmMailing/edit-unified.html b/partials/crmMailing/edit-unified.html index 548e6c46cf..005c57178d 100644 --- a/partials/crmMailing/edit-unified.html +++ b/partials/crmMailing/edit-unified.html @@ -37,7 +37,7 @@
-
+
diff --git a/partials/crmMailing/edit-unified2.html b/partials/crmMailing/edit-unified2.html index 4f2905254c..9140e522cd 100644 --- a/partials/crmMailing/edit-unified2.html +++ b/partials/crmMailing/edit-unified2.html @@ -30,7 +30,7 @@
-
+
diff --git a/partials/crmMailing/edit-wizard.html b/partials/crmMailing/edit-wizard.html index 472577ce72..1548e5b3c0 100644 --- a/partials/crmMailing/edit-wizard.html +++ b/partials/crmMailing/edit-wizard.html @@ -26,7 +26,7 @@
-
+
diff --git a/partials/crmMailing/edit.html b/partials/crmMailing/edit.html index 39db68f606..f6ed9c29f1 100644 --- a/partials/crmMailing/edit.html +++ b/partials/crmMailing/edit.html @@ -36,7 +36,7 @@
-
+
diff --git a/partials/crmMailing/preview.html b/partials/crmMailing/preview.html index 65111542f7..4c6cab2836 100644 --- a/partials/crmMailing/preview.html +++ b/partials/crmMailing/preview.html @@ -1,4 +1,7 @@ -
+ +
@@ -32,7 +35,7 @@ placeholder="example@example.org" />
- +
@@ -49,7 +52,7 @@
- +
diff --git a/partials/crmMailing/review.html b/partials/crmMailing/review.html index 01a26f1f55..f8b9bec20f 100644 --- a/partials/crmMailing/review.html +++ b/partials/crmMailing/review.html @@ -20,11 +20,9 @@ Required vars: mailing
- + {{ts('HTML')}} + {{ts('Plain Text')}} +
diff --git a/partials/crmMailingAB/edit.html b/partials/crmMailingAB/edit.html index a0fff6206e..ae935fde70 100644 --- a/partials/crmMailingAB/edit.html +++ b/partials/crmMailingAB/edit.html @@ -80,10 +80,10 @@
-
+
-
+
@@ -118,7 +118,7 @@
-
+
@@ -153,7 +153,7 @@
-
+
-- 2.25.1