$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 = {
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);
});
_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;
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())
</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}}"