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/:id', {
17 templateUrl
: '~/crmMailingAB/edit.html',
18 controller
: 'CrmMailingABEditCtrl',
20 abtest: function ($route
, CrmMailingAB
) {
21 var abtest
= new CrmMailingAB($route
.current
.params
.id
== 'new' ? null : $route
.current
.params
.id
);
26 $routeProvider
.when('/abtest/:id/report', {
27 templateUrl
: '~/crmMailingAB/report.html',
28 controller
: 'CrmMailingABReportCtrl',
30 abtest: function ($route
, CrmMailingAB
) {
31 var abtest
= new CrmMailingAB($route
.current
.params
.id
);
39 angular
.module('crmMailingAB').controller('CrmMailingABListCtrl', function ($scope
, mailingABList
, crmMailingABCriteria
, crmMailingABStatus
) {
40 var ts
= $scope
.ts
= CRM
.ts(null);
41 $scope
.mailingABList
= mailingABList
.values
;
42 $scope
.crmMailingABCriteria
= crmMailingABCriteria
;
43 $scope
.crmMailingABStatus
= crmMailingABStatus
;
46 angular
.module('crmMailingAB').controller('CrmMailingABEditCtrl', function ($scope
, abtest
, crmMailingABCriteria
, crmMailingMgr
, crmMailingPreviewMgr
, crmStatus
, $q
, $location
) {
47 $scope
.abtest
= abtest
;
48 var ts
= $scope
.ts
= CRM
.ts(null);
49 $scope
.crmMailingABCriteria
= crmMailingABCriteria
;
50 $scope
.crmMailingConst
= CRM
.crmMailing
;
52 $scope
.isSubmitted
= function isSubmitted() {
53 return _
.size(abtest
.mailings
.a
.jobs
) > 0 || _
.size(abtest
.mailings
.b
.jobs
) > 0;
56 $scope
.sync
= function sync() {
57 abtest
.mailings
.a
.name
= ts('Test A (%1)', {1: abtest
.ab
.name
});
58 abtest
.mailings
.b
.name
= ts('Test B (%1)', {1: abtest
.ab
.name
});
59 abtest
.mailings
.c
.name
= ts('Winner (%1)', {1: abtest
.ab
.name
});
61 var criteria
= crmMailingABCriteria
.get(abtest
.ab
.testing_criteria_id
);
63 // TODO review fields exposed in UI and make sure the sync rules match
64 switch (criteria
.name
) {
66 crmMailingMgr
.mergeInto(abtest
.mailings
.b
, abtest
.mailings
.a
, [
74 crmMailingMgr
.mergeInto(abtest
.mailings
.b
, abtest
.mailings
.a
, [
82 case 'Two different emails':
83 crmMailingMgr
.mergeInto(abtest
.mailings
.b
, abtest
.mailings
.a
, [
95 throw "Unrecognized testing_criteria";
98 crmMailingMgr
.mergeInto(abtest
.mailings
.c
, abtest
.mailings
.a
, ['name']);
103 $scope
.save
= function save() {
105 return crmStatus({start
: ts('Saving...'), success
: ts('Saved')}, abtest
.save().then(updateUrl
));
109 $scope
.previewMailing
= function previewMailing(mailingName
, mode
) {
111 return crmMailingPreviewMgr
.preview(abtest
.mailings
[mailingName
], mode
);
115 $scope
.sendTest
= function sendTest(mailingName
, recipient
) {
117 return crmStatus({start
: ts('Saving...'), success
: ''}, abtest
.save().then(updateUrl
))
119 crmMailingPreviewMgr
.sendTest(abtest
.mailings
[mailingName
], recipient
);
124 $scope
.delete = function () {
125 return crmStatus({start
: ts('Deleting...'), success
: ts('Deleted')}, abtest
.delete().then(leave
));
129 $scope
.submit
= function submit() {
131 return crmStatus({start
: ts('Saving...'), success
: ''}, abtest
.save())
133 return crmStatus({start
: ts('Submitting...'), success
: ts('Submitted')}, abtest
.submitTest());
134 // Note: We're going to leave, so we don't care that submit() modifies several server-side records.
135 // If we stayed on this page, then we'd care about updating and call: abtest.submitTest().then(...abtest.load()...)
141 $location
.path('abtest');
145 function updateCriteriaName() {
146 var criteria
= crmMailingABCriteria
.get($scope
.abtest
.ab
.testing_criteria_id
);
147 $scope
.criteriaName
= criteria
? criteria
.name
: null;
150 // Transition URL "/abtest/new" => "/abtest/123"
151 function updateUrl() {
152 var parts
= $location
.path().split('/'); // e.g. "/abtest/new" or "/abtest/123/wizard"
153 if (parts
[2] != $scope
.abtest
.ab
.id
) {
154 parts
[2] = $scope
.abtest
.ab
.id
;
155 $location
.path(parts
.join('/'));
157 // FIXME: Angular unnecessarily refreshes UI
158 // WARNING: Changing the URL triggers a full reload. Any pending AJAX operations
159 // could be inconsistently applied. Run updateUrl() after other changes complete.
164 updateCriteriaName();
166 $scope
.$watch('abtest.ab.testing_criteria_id', updateCriteriaName
);
169 angular
.module('crmMailingAB').controller('CrmMailingABReportCtrl', function ($scope
, abtest
, crmApi
, crmMailingPreviewMgr
, dialogService
) {
170 var ts
= $scope
.ts
= CRM
.ts(null);
172 $scope
.abtest
= abtest
;
175 crmApi('Mailing', 'stats', {mailing_id
: abtest
.ab
.mailing_id_a
}).then(function(data
){
176 $scope
.stats
.a
= data
.values
[abtest
.ab
.mailing_id_a
];
178 crmApi('Mailing', 'stats', {mailing_id
: abtest
.ab
.mailing_id_b
}).then(function(data
){
179 $scope
.stats
.b
= data
.values
[abtest
.ab
.mailing_id_b
];
181 crmApi('Mailing', 'stats', {mailing_id
: abtest
.ab
.mailing_id_c
}).then(function(data
){
182 $scope
.stats
.c
= data
.values
[abtest
.ab
.mailing_id_c
];
185 $scope
.previewMailing
= function previewMailing(mailingName
, mode
) {
186 return crmMailingPreviewMgr
.preview(abtest
.mailings
[mailingName
], mode
);
188 $scope
.selectWinner
= function selectWinner(mailingName
) {
191 mailingName
: mailingName
196 title
: ts('Select Winner (%1)', {
197 1: mailingName
.toUpperCase()
200 return dialogService
.open('selectWinnerDialog', '~/crmMailingAB/selectWinner.html', model
, options
);
205 angular
.module('crmMailingAB').controller('CrmMailingABWinnerDialogCtrl', function ($scope
, $timeout
, dialogService
, crmMailingMgr
, crmStatus
) {
206 var ts
= $scope
.ts
= CRM
.ts(null);
207 var abtest
= $scope
.abtest
= $scope
.model
.abtest
;
208 var mailingName
= $scope
.model
.mailingName
;
210 var titles
= {a
: ts('Mailing A'), b
: ts('Mailing B')};
211 $scope
.mailingTitle
= titles
[mailingName
];
214 // When using dialogService with a button bar, the major button actions
215 // need to be registered with the dialog widget (and not embedded in
216 // the body of the dialog).
218 buttons
[ts('Select Winner')] = function () {
219 crmMailingMgr
.mergeInto(abtest
.mailings
.c
, abtest
.mailings
[mailingName
], [
225 crmStatus({start
: ts('Saving...'), success
: ''}, abtest
.save())
227 return crmStatus({start
: ts('Submitting...'), success
: ts('Submitted')},
228 abtest
.submitFinal().then(function(){
229 return abtest
.load();
233 dialogService
.close('selectWinnerDialog', abtest
);
236 buttons
[ts('Cancel')] = function () {
237 dialogService
.cancel('selectWinnerDialog');
239 dialogService
.setButtons('selectWinnerDialog', buttons
);
245 })(angular
, CRM
.$, CRM
._
);