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});
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/edit.html',
33 controller
: 'CrmMailingABEditCtrl',
35 abtest: function ($route
, CrmMailingAB
) {
36 var abtest
= new CrmMailingAB($route
.current
.params
.id
== 'new' ? null : $route
.current
.params
.id
);
41 $routeProvider
.when('/abtest/:id/report', {
42 templateUrl
: '~/crmMailingAB/report.html',
43 controller
: 'CrmMailingABReportCtrl',
45 abtest: function ($route
, CrmMailingAB
) {
46 var abtest
= new CrmMailingAB($route
.current
.params
.id
);
54 angular
.module('crmMailingAB').controller('CrmMailingABListCtrl', function($scope
, mailingABList
, crmMailingABCriteria
, crmMailingABStatus
, fields
) {
55 var ts
= $scope
.ts
= CRM
.ts(null);
56 $scope
.mailingABList
= _
.values(mailingABList
.values
);
57 $scope
.crmMailingABCriteria
= crmMailingABCriteria
;
58 $scope
.crmMailingABStatus
= crmMailingABStatus
;
59 $scope
.fields
= fields
;
63 angular
.module('crmMailingAB').controller('CrmMailingABNewCtrl', function ($scope
, abtest
, $location
) {
64 // Transition URL "/abtest/new/foo" => "/abtest/123/foo"
65 var parts
= $location
.path().split('/'); // e.g. "/mailing/new" or "/mailing/123/wizard"
67 $location
.path(parts
.join('/'));
71 angular
.module('crmMailingAB').controller('CrmMailingABEditCtrl', function ($scope
, abtest
, crmMailingABCriteria
, crmMailingMgr
, crmMailingPreviewMgr
, crmStatus
, $q
, $location
, crmBlocker
, $interval
) {
72 $scope
.abtest
= abtest
;
73 var ts
= $scope
.ts
= CRM
.ts(null);
74 var block
= $scope
.block
= crmBlocker();
75 $scope
.crmMailingABCriteria
= crmMailingABCriteria
;
76 $scope
.crmMailingConst
= CRM
.crmMailing
;
78 $scope
.isSubmitted
= function isSubmitted() {
79 return _
.size(abtest
.mailings
.a
.jobs
) > 0 || _
.size(abtest
.mailings
.b
.jobs
) > 0;
82 $scope
.sync
= function sync() {
83 abtest
.mailings
.a
.name
= ts('Test A (%1)', {1: abtest
.ab
.name
});
84 abtest
.mailings
.b
.name
= ts('Test B (%1)', {1: abtest
.ab
.name
});
85 abtest
.mailings
.c
.name
= ts('Winner (%1)', {1: abtest
.ab
.name
});
87 if (abtest
.ab
.testing_criteria
) {
88 // TODO review fields exposed in UI and make sure the sync rules match
89 switch (abtest
.ab
.testing_criteria
) {
91 crmMailingMgr
.mergeInto(abtest
.mailings
.b
, abtest
.mailings
.a
, [
98 crmMailingMgr
.mergeInto(abtest
.mailings
.b
, abtest
.mailings
.a
, [
106 crmMailingMgr
.mergeInto(abtest
.mailings
.b
, abtest
.mailings
.a
, [
113 'override_verp', // keep override_verp and replyto_Email linked
119 throw "Unrecognized testing_criteria";
122 crmMailingMgr
.mergeInto(abtest
.mailings
.c
, abtest
.mailings
.a
, ['name']);
127 $scope
.save
= function save() {
128 return block(crmStatus({start
: ts('Saving...'), success
: ts('Saved')}, abtest
.save()));
132 $scope
.previewMailing
= function previewMailing(mailingName
, mode
) {
133 return crmMailingPreviewMgr
.preview(abtest
.mailings
[mailingName
], mode
);
137 $scope
.sendTest
= function sendTest(mailingName
, recipient
) {
138 return block(crmStatus({start
: ts('Saving...'), success
: ''}, abtest
.save())
140 crmMailingPreviewMgr
.sendTest(abtest
.mailings
[mailingName
], recipient
);
145 $scope
.delete = function () {
146 return block(crmStatus({start
: ts('Deleting...'), success
: ts('Deleted')}, abtest
.delete().then($scope
.leave
)));
150 $scope
.submit
= function submit() {
151 if (block
.check() || $scope
.crmMailingAB
.$invalid
) {
154 return block(crmStatus({start
: ts('Saving...'), success
: ''}, abtest
.save())
156 return crmStatus({start
: ts('Submitting...'), success
: ts('Submitted')}, abtest
.submitTest());
157 // Note: We're going to leave, so we don't care that submit() modifies several server-side records.
158 // If we stayed on this page, then we'd care about updating and call: abtest.submitTest().then(...abtest.load()...)
160 ).then($scope
.leave
);
163 $scope
.leave
= function leave() {
164 $location
.path('abtest');
169 var syncJob
= $interval($scope
.sync
, 333);
170 $scope
.$on('$destroy', function(){
171 $interval
.cancel(syncJob
);
175 angular
.module('crmMailingAB').controller('CrmMailingABReportCtrl', function ($scope
, crmApi
, crmMailingPreviewMgr
, dialogService
) {
176 var ts
= $scope
.ts
= CRM
.ts(null);
179 crmApi('Mailing', 'stats', {mailing_id
: $scope
.abtest
.ab
.mailing_id_a
}).then(function(data
){
180 $scope
.stats
.a
= data
.values
[$scope
.abtest
.ab
.mailing_id_a
];
182 crmApi('Mailing', 'stats', {mailing_id
: $scope
.abtest
.ab
.mailing_id_b
}).then(function(data
){
183 $scope
.stats
.b
= data
.values
[$scope
.abtest
.ab
.mailing_id_b
];
185 crmApi('Mailing', 'stats', {mailing_id
: $scope
.abtest
.ab
.mailing_id_c
}).then(function(data
){
186 $scope
.stats
.c
= data
.values
[$scope
.abtest
.ab
.mailing_id_c
];
189 $scope
.previewMailing
= function previewMailing(mailingName
, mode
) {
190 return crmMailingPreviewMgr
.preview(abtest
.mailings
[mailingName
], mode
);
192 $scope
.selectWinner
= function selectWinner(mailingName
) {
194 abtest
: $scope
.abtest
,
195 mailingName
: mailingName
197 var options
= CRM
.utils
.adjustDialogDefaults({
199 title
: ts('Select Winner (%1)', {
200 1: mailingName
.toUpperCase()
203 return dialogService
.open('selectWinnerDialog', '~/crmMailingAB/selectWinner.html', model
, options
);
208 angular
.module('crmMailingAB').controller('CrmMailingABWinnerDialogCtrl', function ($scope
, $timeout
, dialogService
, crmMailingMgr
, crmStatus
) {
209 var ts
= $scope
.ts
= CRM
.ts(null);
210 var abtest
= $scope
.abtest
= $scope
.model
.abtest
;
211 var mailingName
= $scope
.model
.mailingName
;
213 var titles
= {a
: ts('Mailing A'), b
: ts('Mailing B')};
214 $scope
.mailingTitle
= titles
[mailingName
];
217 // When using dialogService with a button bar, the major button actions
218 // need to be registered with the dialog widget (and not embedded in
219 // the body of the dialog).
221 buttons
[ts('Select Winner')] = function () {
222 crmMailingMgr
.mergeInto(abtest
.mailings
.c
, abtest
.mailings
[mailingName
], [
227 crmStatus({start
: ts('Saving...'), success
: ''}, abtest
.save())
229 return crmStatus({start
: ts('Submitting...'), success
: ts('Submitted')},
230 abtest
.submitFinal().then(function(){
231 return abtest
.load();
235 dialogService
.close('selectWinnerDialog', abtest
);
238 buttons
[ts('Cancel')] = function () {
239 dialogService
.cancel('selectWinnerDialog');
241 dialogService
.setButtons('selectWinnerDialog', buttons
);
247 })(angular
, CRM
.$, CRM
._
);