1 (function (angular
, $, _
) {
3 angular
.module('crmMailingAB', ['ngRoute', 'ui.utils', '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});
14 fields: function(crmMetadata
){
15 return crmMetadata
.getFields('MailingAB');
19 $routeProvider
.when('/abtest/new', {
20 template
: '<p>' + ts('Initializing...') + '</p>',
21 controller
: 'CrmMailingABNewCtrl',
23 abtest: function ($route
, CrmMailingAB
) {
24 var abtest
= new CrmMailingAB(null);
25 return abtest
.load().then(function(){
31 $routeProvider
.when('/abtest/:id', {
32 templateUrl
: '~/crmMailingAB/main.html',
33 controller
: 'CrmMailingABEditCtrl',
35 abtest: function ($route
, CrmMailingAB
) {
36 var abtest
= new CrmMailingAB($route
.current
.params
.id
== 'new' ? null : $route
.current
.params
.id
);
44 angular
.module('crmMailingAB').controller('CrmMailingABListCtrl', function($scope
, mailingABList
, crmMailingABCriteria
, crmMailingABStatus
, fields
) {
45 var ts
= $scope
.ts
= CRM
.ts(null);
46 $scope
.mailingABList
= _
.values(mailingABList
.values
);
47 $scope
.crmMailingABCriteria
= crmMailingABCriteria
;
48 $scope
.crmMailingABStatus
= crmMailingABStatus
;
49 $scope
.fields
= fields
;
53 angular
.module('crmMailingAB').controller('CrmMailingABNewCtrl', function ($scope
, abtest
, $location
) {
54 // Transition URL "/abtest/new/foo" => "/abtest/123/foo"
55 var parts
= $location
.path().split('/'); // e.g. "/mailing/new" or "/mailing/123/wizard"
57 $location
.path(parts
.join('/'));
61 angular
.module('crmMailingAB').controller('CrmMailingABEditCtrl', function ($scope
, abtest
, crmMailingABCriteria
, crmMailingMgr
, crmMailingPreviewMgr
, crmStatus
, $q
, $location
, crmBlocker
, $interval
, $timeout
, CrmAutosaveCtrl
, dialogService
) {
62 $scope
.abtest
= abtest
;
63 var ts
= $scope
.ts
= CRM
.ts(null);
64 var block
= $scope
.block
= crmBlocker();
65 $scope
.crmUrl
= CRM
.url
;
66 var myAutosave
= null;
67 $scope
.crmMailingABCriteria
= crmMailingABCriteria
;
68 $scope
.crmMailingConst
= CRM
.crmMailing
;
69 $scope
.checkPerm
= CRM
.checkPerm
;
71 $scope
.isSubmitted
= function isSubmitted() {
72 return _
.size(abtest
.mailings
.a
.jobs
) > 0 || _
.size(abtest
.mailings
.b
.jobs
) > 0;
75 $scope
.sync
= function sync() {
76 abtest
.mailings
.a
.name
= ts('Test A (%1)', {1: abtest
.ab
.name
});
77 abtest
.mailings
.b
.name
= ts('Test B (%1)', {1: abtest
.ab
.name
});
78 abtest
.mailings
.c
.name
= ts('Final (%1)', {1: abtest
.ab
.name
});
80 if (abtest
.ab
.testing_criteria
) {
81 // TODO review fields exposed in UI and make sure the sync rules match
82 switch (abtest
.ab
.testing_criteria
) {
84 crmMailingMgr
.mergeInto(abtest
.mailings
.b
, abtest
.mailings
.a
, [
91 crmMailingMgr
.mergeInto(abtest
.mailings
.b
, abtest
.mailings
.a
, [
99 crmMailingMgr
.mergeInto(abtest
.mailings
.b
, abtest
.mailings
.a
, [
106 'override_verp', // keep override_verp and replyto_Email linked
112 throw "Unrecognized testing_criteria";
115 crmMailingMgr
.mergeInto(abtest
.mailings
.c
, abtest
.mailings
.a
, ['name']);
120 $scope
.save
= function save() {
121 return block(crmStatus({start
: ts('Saving...'), success
: ts('Saved')}, abtest
.save()));
125 $scope
.previewMailing
= function previewMailing(mailingName
, mode
) {
126 return crmMailingPreviewMgr
.preview(abtest
.mailings
[mailingName
], mode
);
130 $scope
.sendTest
= function sendTest(mailingName
, recipient
) {
131 return block(crmStatus({start
: ts('Saving...'), success
: ''}, abtest
.save())
133 crmMailingPreviewMgr
.sendTest(abtest
.mailings
[mailingName
], recipient
);
138 $scope
.delete = function () {
139 return block(crmStatus({start
: ts('Deleting...'), success
: ts('Deleted')}, abtest
.delete().then($scope
.leave
)));
143 $scope
.submit
= function submit() {
144 if (block
.check() || $scope
.crmMailingAB
.$invalid
) {
147 return block(crmStatus({start
: ts('Saving...'), success
: ''}, abtest
.save())
149 return crmStatus({start
: ts('Submitting...'), success
: ts('Submitted')}, myAutosave
.suspend(abtest
.submitTest()));
150 // Note: We're going to leave, so we don't care that submit() modifies several server-side records.
151 // If we stayed on this page, then we'd care about updating and call: abtest.submitTest().then(...abtest.load()...)
156 $scope
.leave
= function leave() {
157 $location
.path('abtest');
161 $scope
.selectWinner
= function selectWinner(mailingName
) {
163 abtest
: $scope
.abtest
,
164 mailingName
: mailingName
166 var options
= CRM
.utils
.adjustDialogDefaults({
170 title
: ts('Select Final Mailing (Test %1)', {
171 1: mailingName
.toUpperCase()
174 return myAutosave
.suspend(dialogService
.open('selectWinnerDialog', '~/crmMailingAB/selectWinner.html', model
, options
));
178 var syncJob
= $interval($scope
.sync
, 333);
179 $scope
.$on('$destroy', function(){
180 $interval
.cancel(syncJob
);
183 myAutosave
= new CrmAutosaveCtrl({
186 return abtest
.ab
.status
== 'Draft' && $scope
.sync();
189 return abtest
.getAutosaveSignature();
192 return $scope
.crmMailingAB
;
195 $timeout(myAutosave
.start
);
196 $scope
.$on('$destroy', myAutosave
.stop
);
199 angular
.module('crmMailingAB').controller('CrmMailingABReportCtrl', function ($scope
, crmApi
, crmMailingStats
) {
200 var ts
= $scope
.ts
= CRM
.ts(null);
202 var CrmMailingABReportCnt
= 1, activeMailings
= null;
203 $scope
.getActiveMailings = function() {
204 if ($scope
.abtest
.$CrmMailingABReportCnt
!= CrmMailingABReportCnt
) {
205 $scope
.abtest
.$CrmMailingABReportCnt
= ++CrmMailingABReportCnt
;
207 {name
: 'a', title
: ts('Mailing A'), mailing
: $scope
.abtest
.mailings
.a
, attachments
: $scope
.abtest
.attachments
.a
},
208 {name
: 'b', title
: ts('Mailing B'), mailing
: $scope
.abtest
.mailings
.b
, attachments
: $scope
.abtest
.attachments
.b
}
210 if ($scope
.abtest
.ab
.status
== 'Final') {
211 activeMailings
.push({name
: 'c', title
: ts('Final'), mailing
: $scope
.abtest
.mailings
.c
, attachments
: $scope
.abtest
.attachments
.c
});
214 return activeMailings
;
217 crmMailingStats
.getStats({
218 a
: $scope
.abtest
.ab
.mailing_id_a
,
219 b
: $scope
.abtest
.ab
.mailing_id_b
,
220 c
: $scope
.abtest
.ab
.mailing_id_c
221 }).then(function(stats
) {
222 $scope
.stats
= stats
;
225 $scope
.statTypes
= crmMailingStats
.getStatTypes();
226 $scope
.statUrl
= function statUrl(mailing
, statType
, view
) {
227 return crmMailingStats
.getUrl(mailing
, statType
, view
, 'abtest/' + $scope
.abtest
.ab
.id
);
230 $scope
.checkPerm
= CRM
.checkPerm
;
233 angular
.module('crmMailingAB').controller('CrmMailingABWinnerDialogCtrl', function ($scope
, $timeout
, dialogService
, crmMailingMgr
, crmStatus
) {
234 var ts
= $scope
.ts
= CRM
.ts(null);
235 var abtest
= $scope
.abtest
= $scope
.model
.abtest
;
236 var mailingName
= $scope
.model
.mailingName
;
238 var titles
= {a
: ts('Mailing A'), b
: ts('Mailing B')};
239 $scope
.mailingTitle
= titles
[mailingName
];
242 // When using dialogService with a button bar, the major button actions
243 // need to be registered with the dialog widget (and not embedded in
244 // the body of the dialog).
247 text
: ts('Submit final mailing'),
248 icons
: {primary
: 'ui-icon-check'},
250 crmMailingMgr
.mergeInto(abtest
.mailings
.c
, abtest
.mailings
[mailingName
], [
255 crmStatus({start
: ts('Saving...'), success
: ''}, abtest
.save())
257 return crmStatus({start
: ts('Submitting...'), success
: ts('Submitted')},
258 abtest
.submitFinal().then(function(r
){
259 delete abtest
.$CrmMailingABReportCnt
;
264 dialogService
.close('selectWinnerDialog', abtest
);
270 icons
: {primary
: 'ui-icon-close'},
272 dialogService
.cancel('selectWinnerDialog');
276 dialogService
.setButtons('selectWinnerDialog', buttons
);
282 })(angular
, CRM
.$, CRM
._
);