1 (function (angular
, $, _
) {
3 angular
.module('crmMailingAB', ['ngRoute', 'ui.utils', 'ngSanitize', 'crmUi', 'crmAttachment', 'crmMailing', 'crmD3']);
4 angular
.module('crmMailingAB').config([
6 function ($routeProvider
) {
7 $routeProvider
.when('/abtest', {
8 templateUrl
: '~/crmMailingAB/list.html',
9 controller
: 'CrmMailingABListCtrl',
11 mailingABList: function ($route
, crmApi
) {
12 return crmApi('MailingAB', 'get', {rowCount
: 0});
16 $routeProvider
.when('/abtest/new', {
17 template
: '<p>' + ts('Initializing...') + '</p>',
18 controller
: 'CrmMailingABNewCtrl',
20 abtest: function ($route
, CrmMailingAB
) {
21 var abtest
= new CrmMailingAB(null);
22 return abtest
.load().then(function(){
28 $routeProvider
.when('/abtest/:id', {
29 templateUrl
: '~/crmMailingAB/edit.html',
30 controller
: 'CrmMailingABEditCtrl',
32 abtest: function ($route
, CrmMailingAB
) {
33 var abtest
= new CrmMailingAB($route
.current
.params
.id
== 'new' ? null : $route
.current
.params
.id
);
38 $routeProvider
.when('/abtest/:id/report', {
39 templateUrl
: '~/crmMailingAB/report.html',
40 controller
: 'CrmMailingABReportCtrl',
42 abtest: function ($route
, CrmMailingAB
) {
43 var abtest
= new CrmMailingAB($route
.current
.params
.id
);
51 angular
.module('crmMailingAB').controller('CrmMailingABListCtrl', function ($scope
, mailingABList
, crmMailingABCriteria
, crmMailingABStatus
) {
52 var ts
= $scope
.ts
= CRM
.ts(null);
53 $scope
.mailingABList
= mailingABList
.values
;
54 $scope
.crmMailingABCriteria
= crmMailingABCriteria
;
55 $scope
.crmMailingABStatus
= crmMailingABStatus
;
58 angular
.module('crmMailingAB').controller('CrmMailingABNewCtrl', function ($scope
, abtest
, $location
) {
59 // Transition URL "/abtest/new/foo" => "/abtest/123/foo"
60 var parts
= $location
.path().split('/'); // e.g. "/mailing/new" or "/mailing/123/wizard"
62 $location
.path(parts
.join('/'));
66 angular
.module('crmMailingAB').controller('CrmMailingABEditCtrl', function ($scope
, abtest
, crmMailingABCriteria
, crmMailingMgr
, crmMailingPreviewMgr
, crmStatus
, $q
, $location
, crmBlocker
, $interval
) {
67 $scope
.abtest
= abtest
;
68 var ts
= $scope
.ts
= CRM
.ts(null);
69 var block
= $scope
.block
= crmBlocker();
70 $scope
.crmMailingABCriteria
= crmMailingABCriteria
;
71 $scope
.crmMailingConst
= CRM
.crmMailing
;
73 $scope
.isSubmitted
= function isSubmitted() {
74 return _
.size(abtest
.mailings
.a
.jobs
) > 0 || _
.size(abtest
.mailings
.b
.jobs
) > 0;
77 $scope
.sync
= function sync() {
78 abtest
.mailings
.a
.name
= ts('Test A (%1)', {1: abtest
.ab
.name
});
79 abtest
.mailings
.b
.name
= ts('Test B (%1)', {1: abtest
.ab
.name
});
80 abtest
.mailings
.c
.name
= ts('Winner (%1)', {1: abtest
.ab
.name
});
82 var criteria
= crmMailingABCriteria
.get(abtest
.ab
.testing_criteria_id
);
84 // TODO review fields exposed in UI and make sure the sync rules match
85 switch (criteria
.name
) {
87 crmMailingMgr
.mergeInto(abtest
.mailings
.b
, abtest
.mailings
.a
, [
94 crmMailingMgr
.mergeInto(abtest
.mailings
.b
, abtest
.mailings
.a
, [
101 case 'Two different emails':
102 crmMailingMgr
.mergeInto(abtest
.mailings
.b
, abtest
.mailings
.a
, [
109 'override_verp', // keep override_verp and replyto_Email linked
115 throw "Unrecognized testing_criteria";
118 crmMailingMgr
.mergeInto(abtest
.mailings
.c
, abtest
.mailings
.a
, ['name']);
123 $scope
.save
= function save() {
124 return block(crmStatus({start
: ts('Saving...'), success
: ts('Saved')}, abtest
.save()));
128 $scope
.previewMailing
= function previewMailing(mailingName
, mode
) {
129 return crmMailingPreviewMgr
.preview(abtest
.mailings
[mailingName
], mode
);
133 $scope
.sendTest
= function sendTest(mailingName
, recipient
) {
134 return block(crmStatus({start
: ts('Saving...'), success
: ''}, abtest
.save())
136 crmMailingPreviewMgr
.sendTest(abtest
.mailings
[mailingName
], recipient
);
141 $scope
.delete = function () {
142 return block(crmStatus({start
: ts('Deleting...'), success
: ts('Deleted')}, abtest
.delete().then($scope
.leave
)));
146 $scope
.submit
= function submit() {
147 if (block
.check() || $scope
.crmMailingAB
.$invalid
) {
150 return block(crmStatus({start
: ts('Saving...'), success
: ''}, abtest
.save())
152 return crmStatus({start
: ts('Submitting...'), success
: ts('Submitted')}, abtest
.submitTest());
153 // Note: We're going to leave, so we don't care that submit() modifies several server-side records.
154 // If we stayed on this page, then we'd care about updating and call: abtest.submitTest().then(...abtest.load()...)
156 ).then($scope
.leave
);
159 $scope
.leave
= function leave() {
160 $location
.path('abtest');
164 function updateCriteriaName() {
165 var criteria
= crmMailingABCriteria
.get($scope
.abtest
.ab
.testing_criteria_id
);
166 $scope
.criteriaName
= criteria
? criteria
.name
: null;
170 updateCriteriaName();
171 $scope
.$watch('abtest.ab.testing_criteria_id', updateCriteriaName
);
172 var syncJob
= $interval($scope
.sync
, 333);
173 $scope
.$on('$destroy', function(){
174 $interval
.cancel(syncJob
);
178 angular
.module('crmMailingAB').controller('CrmMailingABReportCtrl', function ($scope
, abtest
, crmApi
, crmMailingPreviewMgr
, dialogService
) {
179 var ts
= $scope
.ts
= CRM
.ts(null);
181 $scope
.abtest
= abtest
;
184 crmApi('Mailing', 'stats', {mailing_id
: abtest
.ab
.mailing_id_a
}).then(function(data
){
185 $scope
.stats
.a
= data
.values
[abtest
.ab
.mailing_id_a
];
187 crmApi('Mailing', 'stats', {mailing_id
: abtest
.ab
.mailing_id_b
}).then(function(data
){
188 $scope
.stats
.b
= data
.values
[abtest
.ab
.mailing_id_b
];
190 crmApi('Mailing', 'stats', {mailing_id
: abtest
.ab
.mailing_id_c
}).then(function(data
){
191 $scope
.stats
.c
= data
.values
[abtest
.ab
.mailing_id_c
];
194 $scope
.previewMailing
= function previewMailing(mailingName
, mode
) {
195 return crmMailingPreviewMgr
.preview(abtest
.mailings
[mailingName
], mode
);
197 $scope
.selectWinner
= function selectWinner(mailingName
) {
200 mailingName
: mailingName
202 var options
= CRM
.utils
.adjustDialogDefaults({
204 title
: ts('Select Winner (%1)', {
205 1: mailingName
.toUpperCase()
208 return dialogService
.open('selectWinnerDialog', '~/crmMailingAB/selectWinner.html', model
, options
);
213 angular
.module('crmMailingAB').controller('CrmMailingABWinnerDialogCtrl', function ($scope
, $timeout
, dialogService
, crmMailingMgr
, crmStatus
) {
214 var ts
= $scope
.ts
= CRM
.ts(null);
215 var abtest
= $scope
.abtest
= $scope
.model
.abtest
;
216 var mailingName
= $scope
.model
.mailingName
;
218 var titles
= {a
: ts('Mailing A'), b
: ts('Mailing B')};
219 $scope
.mailingTitle
= titles
[mailingName
];
222 // When using dialogService with a button bar, the major button actions
223 // need to be registered with the dialog widget (and not embedded in
224 // the body of the dialog).
226 buttons
[ts('Select Winner')] = function () {
227 crmMailingMgr
.mergeInto(abtest
.mailings
.c
, abtest
.mailings
[mailingName
], [
232 crmStatus({start
: ts('Saving...'), success
: ''}, abtest
.save())
234 return crmStatus({start
: ts('Submitting...'), success
: ts('Submitted')},
235 abtest
.submitFinal().then(function(){
236 return abtest
.load();
240 dialogService
.close('selectWinnerDialog', abtest
);
243 buttons
[ts('Cancel')] = function () {
244 dialogService
.cancel('selectWinnerDialog');
246 dialogService
.setButtons('selectWinnerDialog', buttons
);
252 })(angular
, CRM
.$, CRM
._
);