});
});
- 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};
$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)
});
return crmStatus({start: ts('Submitting...'), success: ts('Submitted')}, promise);
};
+
// @return Promise
$scope.save = function save() {
return crmStatus(null,
})
);
};
+
// @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,
$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"
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._);
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'),
});
});
+ // example: <div crm-mailing-block-preview crm-mailing="myMailing" on-preview="openPreview(myMailing, preview.mode)" on-send="sendEmail(myMailing,preview.recipient)">
+ // 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" <e@ma.il>)
// example: <span crm-mailing-from-address="myPlaceholder" crm-mailing="myMailing"><select ng-model="myPlaceholder.label"></select></span>
// NOTE: This really doesn't belong in a directive. I've tried (and failed) to make this work with a getterSetter binding, eg
// 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
'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'}
}
// 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
}
});
}
};
});
+
+ // 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._);
$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;
};
$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"
</div>
<div crm-ui-accordion crm-title="ts('Preview')">
- <div crm-mailing-block-preview crm-mailing="mailing"/>
+ <div crm-mailing-block-preview crm-mailing="mailing" on-preview="previewMailing(mailing, preview.mode)" on-send="sendTest(mailing, attachments, preview.recipient)" />
</div>
<button ng-click="submit().then(leave)">{{ts('Submit Mailing')}}</button>
<div crm-mailing-block-tracking crm-mailing="mailing"/>
</div>
<div crm-ui-accordion crm-title="ts('Preview')">
- <div crm-mailing-block-preview crm-mailing="mailing"/>
+ <div crm-mailing-block-preview crm-mailing="mailing" on-preview="previewMailing(mailing, preview.mode)" on-send="sendTest(mailing, attachments, preview.recipient)" />
</div>
<div crm-ui-accordion id="tab-schedule" crm-title="ts('Schedule')">
<div crm-mailing-block-schedule crm-mailing="mailing"/>
<div crm-attachments="attachments"/>
</div>
<div crm-ui-accordion crm-title="ts('Preview')">
- <div crm-mailing-block-preview crm-mailing="mailing"/>
+ <div crm-mailing-block-preview crm-mailing="mailing" on-preview="previewMailing(mailing, preview.mode)" on-send="sendTest(mailing, attachments, preview.recipient)" />
</div>
</div>
</div>
</div>
<div crm-ui-accordion crm-title="ts('Preview')">
- <div crm-mailing-block-preview crm-mailing="mailing"/>
+ <div crm-mailing-block-preview crm-mailing="mailing" on-preview="previewMailing(mailing, preview.mode)" on-send="sendTest(mailing, attachments, preview.recipient)" />
</div>
</div>
<div crm-ui-wizard-step crm-title="ts('Review and Schedule')">
-<div ng-controller="PreviewMailingCtrl" class="crmMailing-preview">
+<!--
+Vars: mailing:obj, testContact:obj, testGroup:obj, crmMailing:FormController
+-->
+<div class="crmMailing-preview">
<!-- Note:
In Firefox (at least), clicking the preview buttons causes the browser to display validation warnings
for unrelated fields *and* display preview. To avoid this weird UX, we disable preview buttons when the form is incomplete/invalid.
<em>({{ts('No content to preview')}})</em>
</div>
<div ng-hide="!mailing.body_html">
- <button ng-disabled="crmMailing.$invalid" ng-click="previewHtml()">{{ts('Preview as HTML')}}</button>
+ <button ng-disabled="crmMailing.$invalid" ng-click="doPreview('html')">{{ts('Preview as HTML')}}</button>
</div>
<div ng-hide="!mailing.body_text">
- <button ng-disabled="crmMailing.$invalid" ng-click="previewText()">{{ts('Preview as Plain Text')}}</button>
+ <button ng-disabled="crmMailing.$invalid" ng-click="doPreview('text')">{{ts('Preview as Plain Text')}}</button>
</div>
<!--
<div ng-hide="!mailing.body_html && !mailing.body_text">
- <button ng-disabled="crmMailing.$invalid" ng-click="previewFull()">{{ts('Preview')}}</button>
+ <button ng-disabled="crmMailing.$invalid" ng-click="doPreview('full')">{{ts('Preview')}}</button>
</div>
-->
</div>
placeholder="example@example.org"
/>
</div>
- <button ng-disabled="crmMailing.$invalid || !testContact.email" ng-click="sendTestToContact()">{{ts('Send test')}}</button>
+ <button ng-disabled="crmMailing.$invalid || !testContact.email" ng-click="doSend({email: testContact.email})">{{ts('Send test')}}</button>
</div>
<div class="preview-group" ng-form>
<div>
<option value=""></option>
</select>
</div>
- <button ng-disabled="crmMailing.$invalid || !testGroup.gid" ng-click="sendTestToGroup()">{{ts('Send test')}}</button>
+ <button ng-disabled="crmMailing.$invalid || !testGroup.gid" ng-click="doSend({gid: testGroup.gid})">{{ts('Send test')}}</button>
</div>
<div class="clear"></div>
</div>
</div>
</div>
<div crm-ui-field crm-title="ts('Content')">
- <div ng-controller="PreviewMailingCtrl">
- <span ng-show="mailing.body_html"><a class="crm-hover-button action-item" ng-click="previewHtml()">{{ts('HTML')}} <span class="icon ui-icon-newwin"></span></a></span>
- <span ng-show="mailing.body_text"><a class="crm-hover-button action-item" ng-click="previewText()">{{ts('Plain Text')}} <span class="icon ui-icon-newwin"></span></a></span>
- <!-- TODO: attachments -->
- </div>
+ <span ng-show="mailing.body_html"><a class="crm-hover-button action-item" ng-click="previewMailing(mailing, 'html')">{{ts('HTML')}} <span class="icon ui-icon-newwin"></span></a></span>
+ <span ng-show="mailing.body_text"><a class="crm-hover-button action-item" ng-click="previewMailing(mailing, 'text')">{{ts('Plain Text')}} <span class="icon ui-icon-newwin"></span></a></span>
+ <!-- TODO: attachments -->
</div>
<div crm-ui-field crm-title="ts('Attachments')" ng-show="attachments.files.length > 0 || attachments.uploader.queue.length > 0">
<div ng-repeat="file in attachments.files">
</div>
</div>
<div crm-ui-accordion crm-title="ts('Preview (A)')">
- <div crm-mailing-block-preview crm-mailing="abtest.mailings.a"/>
+ <div crm-mailing-block-preview crm-mailing="abtest.mailings.a" on-preview="previewMailing('a', preview.mode)" on-send="sendTest('a', preview.recipient)" />
</div>
<div crm-ui-accordion crm-title="ts('Preview (B)')">
- <div crm-mailing-block-preview crm-mailing="abtest.mailings.b"/>
+ <div crm-mailing-block-preview crm-mailing="abtest.mailings.b" on-preview="previewMailing('b', preview.mode)" on-send="sendTest('b', preview.recipient)" />
</div>
</div>
<div crm-ui-wizard-step="21" crm-title="ts('Compose (A)')" ng-if="criteriaName == 'Two different emails'">
</div>
</div>
<div crm-ui-accordion crm-title="ts('Preview')">
- <div crm-mailing-block-preview crm-mailing="abtest.mailings.a"/>
+ <div crm-mailing-block-preview crm-mailing="abtest.mailings.a" on-preview="previewMailing('a', preview.mode)" on-send="sendTest('a', preview.recipient)" />
</div>
</div>
<div crm-ui-wizard-step="22" crm-title="ts('Compose (B)')" ng-if="criteriaName == 'Two different emails'">
</div>
</div>
<div crm-ui-accordion crm-title="ts('Preview')">
- <div crm-mailing-block-preview crm-mailing="abtest.mailings.b"/>
+ <div crm-mailing-block-preview crm-mailing="abtest.mailings.b" on-preview="previewMailing('b', preview.mode)" on-send="sendTest('b', preview.recipient)" />
</div>
</div>
<div crm-ui-wizard-step="30" crm-title="ts('Schedule')">