INFRA-132 - Add .jshintrc. Cleanup tests/karama/unit.
[civicrm-core.git] / js / angular-crmMailingAB.js
CommitLineData
70980d8e
TO
1(function (angular, $, _) {
2
360aaa75 3 angular.module('crmMailingAB', ['ngRoute', 'ui.utils', 'ngSanitize', 'crmUi', 'crmAttachment', 'crmMailing', 'crmD3']);
efd95528 4 angular.module('crmMailingAB').config([
70980d8e
TO
5 '$routeProvider',
6 function ($routeProvider) {
efd95528 7 $routeProvider.when('/abtest', {
ef5d18a1 8 templateUrl: '~/crmMailingAB/list.html',
efd95528 9 controller: 'CrmMailingABListCtrl',
70980d8e
TO
10 resolve: {
11 mailingABList: function ($route, crmApi) {
12 return crmApi('MailingAB', 'get', {rowCount: 0});
13 }
14 }
15 });
efd95528 16 $routeProvider.when('/abtest/:id', {
ef5d18a1 17 templateUrl: '~/crmMailingAB/edit.html',
efd95528 18 controller: 'CrmMailingABEditCtrl',
70980d8e
TO
19 resolve: {
20 abtest: function ($route, CrmMailingAB) {
21 var abtest = new CrmMailingAB($route.current.params.id == 'new' ? null : $route.current.params.id);
22 return abtest.load();
23 }
24 }
25 });
360aaa75 26 $routeProvider.when('/abtest/:id/report', {
ef5d18a1 27 templateUrl: '~/crmMailingAB/report.html',
360aaa75
TO
28 controller: 'CrmMailingABReportCtrl',
29 resolve: {
30 abtest: function ($route, CrmMailingAB) {
31 var abtest = new CrmMailingAB($route.current.params.id);
32 return abtest.load();
33 }
34 }
35 });
70980d8e
TO
36 }
37 ]);
38
63430d3c 39 angular.module('crmMailingAB').controller('CrmMailingABListCtrl', function ($scope, mailingABList, crmMailingABCriteria, crmMailingABStatus) {
5d8901af 40 var ts = $scope.ts = CRM.ts(null);
70980d8e 41 $scope.mailingABList = mailingABList.values;
63430d3c
TO
42 $scope.crmMailingABCriteria = crmMailingABCriteria;
43 $scope.crmMailingABStatus = crmMailingABStatus;
a7931384 44 });
70980d8e 45
86c3a327 46 angular.module('crmMailingAB').controller('CrmMailingABEditCtrl', function ($scope, abtest, crmMailingABCriteria, crmMailingMgr, crmMailingPreviewMgr, crmStatus, $q, $location) {
70980d8e 47 $scope.abtest = abtest;
5d8901af 48 var ts = $scope.ts = CRM.ts(null);
af6962d8 49 $scope.crmMailingABCriteria = crmMailingABCriteria;
bcdd7f49 50 $scope.crmMailingConst = CRM.crmMailing;
af6962d8 51
86c3a327
TO
52 $scope.isSubmitted = function isSubmitted() {
53 return _.size(abtest.mailings.a.jobs) > 0 || _.size(abtest.mailings.b.jobs) > 0;
54 };
c9e9a71e 55
70980d8e
TO
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});
60
61 var criteria = crmMailingABCriteria.get(abtest.ab.testing_criteria_id);
62 if (criteria) {
d3b6424f 63 // TODO review fields exposed in UI and make sure the sync rules match
70980d8e
TO
64 switch (criteria.name) {
65 case 'Subject lines':
c9e9a71e
TO
66 crmMailingMgr.mergeInto(abtest.mailings.b, abtest.mailings.a, [
67 'name',
68 'groups',
69 'mailings',
70 'subject'
71 ]);
70980d8e
TO
72 break;
73 case 'From names':
c9e9a71e
TO
74 crmMailingMgr.mergeInto(abtest.mailings.b, abtest.mailings.a, [
75 'name',
76 'groups',
77 'mailings',
78 'from_name',
79 'from_email'
80 ]);
70980d8e
TO
81 break;
82 case 'Two different emails':
83 crmMailingMgr.mergeInto(abtest.mailings.b, abtest.mailings.a, [
84 'name',
c9e9a71e
TO
85 'groups',
86 'mailings',
70980d8e
TO
87 'subject',
88 'from_name',
89 'from_email',
90 'body_html',
91 'body_text'
92 ]);
93 break;
94 default:
95 throw "Unrecognized testing_criteria";
96 }
97 }
98 crmMailingMgr.mergeInto(abtest.mailings.c, abtest.mailings.a, ['name']);
c9e9a71e 99 return $q.when(true);
70980d8e 100 };
86c3a327
TO
101
102 // @return Promise
70980d8e
TO
103 $scope.save = function save() {
104 $scope.sync();
86c3a327 105 return crmStatus({start: ts('Saving...'), success: ts('Saved')}, abtest.save().then(updateUrl));
58dfba8d 106 };
86c3a327 107
58dfba8d
TO
108 // @return Promise
109 $scope.previewMailing = function previewMailing(mailingName, mode) {
c9e9a71e 110 $scope.sync();
58dfba8d
TO
111 return crmMailingPreviewMgr.preview(abtest.mailings[mailingName], mode);
112 };
113
114 // @return Promise
115 $scope.sendTest = function sendTest(mailingName, recipient) {
c9e9a71e 116 $scope.sync();
86c3a327 117 return crmStatus({start: ts('Saving...'), success: ''}, abtest.save().then(updateUrl))
58dfba8d
TO
118 .then(function () {
119 crmMailingPreviewMgr.sendTest(abtest.mailings[mailingName], recipient);
120 });
70980d8e 121 };
86c3a327
TO
122
123 // @return Promise
70980d8e 124 $scope.delete = function () {
b0797ac3 125 return crmStatus({start: ts('Deleting...'), success: ts('Deleted')}, abtest.delete().then(leave));
70980d8e 126 };
86c3a327
TO
127
128 // @return Promise
129 $scope.submit = function submit() {
c9e9a71e 130 $scope.sync();
b0797ac3 131 return crmStatus({start: ts('Saving...'), success: ''}, abtest.save())
86c3a327 132 .then(function () {
32b8b0bf 133 return crmStatus({start: ts('Submitting...'), success: ts('Submitted')}, abtest.submitTest());
c9e9a71e 134 // Note: We're going to leave, so we don't care that submit() modifies several server-side records.
32b8b0bf 135 // If we stayed on this page, then we'd care about updating and call: abtest.submitTest().then(...abtest.load()...)
b0797ac3
TO
136 })
137 .then(leave);
22bc3e48
TO
138 };
139
b0797ac3 140 function leave() {
b0797ac3
TO
141 $location.path('abtest');
142 $location.replace();
143 }
144
22bc3e48 145 function updateCriteriaName() {
f2bad133 146 var criteria = crmMailingABCriteria.get($scope.abtest.ab.testing_criteria_id);
bcdd7f49 147 $scope.criteriaName = criteria ? criteria.name : null;
22bc3e48 148 }
70980d8e 149
86c3a327
TO
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('/'));
156 $location.replace();
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.
160 }
161 }
162
22bc3e48
TO
163 // initialize
164 updateCriteriaName();
70980d8e 165 $scope.sync();
22bc3e48 166 $scope.$watch('abtest.ab.testing_criteria_id', updateCriteriaName);
70980d8e
TO
167 });
168
32b8b0bf 169 angular.module('crmMailingAB').controller('CrmMailingABReportCtrl', function ($scope, abtest, crmApi, crmMailingPreviewMgr, dialogService) {
5d8901af 170 var ts = $scope.ts = CRM.ts(null);
360aaa75
TO
171
172 $scope.abtest = abtest;
173
174 $scope.stats = {};
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];
177 });
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];
180 });
32b8b0bf
TO
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];
183 });
184
185 $scope.previewMailing = function previewMailing(mailingName, mode) {
186 return crmMailingPreviewMgr.preview(abtest.mailings[mailingName], mode);
187 };
188 $scope.selectWinner = function selectWinner(mailingName) {
189 var model = {
190 abtest: abtest,
191 mailingName: mailingName
192 };
193 var options = {
194 autoOpen: false,
195 modal: true,
196 title: ts('Select Winner (%1)', {
197 1: mailingName.toUpperCase()
198 })
199 };
ef5d18a1 200 return dialogService.open('selectWinnerDialog', '~/crmMailingAB/selectWinner.html', model, options);
32b8b0bf
TO
201 };
202 });
203
204
205 angular.module('crmMailingAB').controller('CrmMailingABWinnerDialogCtrl', function ($scope, $timeout, dialogService, crmMailingMgr, crmStatus) {
5d8901af 206 var ts = $scope.ts = CRM.ts(null);
32b8b0bf
TO
207 var abtest = $scope.abtest = $scope.model.abtest;
208 var mailingName = $scope.model.mailingName;
209
210 var titles = {a: ts('Mailing A'), b: ts('Mailing B')};
211 $scope.mailingTitle = titles[mailingName];
212
213 function init() {
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).
217 var buttons = {};
218 buttons[ts('Select Winner')] = function () {
219 crmMailingMgr.mergeInto(abtest.mailings.c, abtest.mailings[mailingName], [
220 'name',
221 'groups',
222 'mailings',
223 'scheduled_date'
224 ]);
225 crmStatus({start: ts('Saving...'), success: ''}, abtest.save())
226 .then(function () {
227 return crmStatus({start: ts('Submitting...'), success: ts('Submitted')},
228 abtest.submitFinal().then(function(){
229 return abtest.load();
230 }));
231 })
232 .then(function(){
233 dialogService.close('selectWinnerDialog', abtest);
234 });
235 };
236 buttons[ts('Cancel')] = function () {
237 dialogService.cancel('selectWinnerDialog');
238 };
239 dialogService.setButtons('selectWinnerDialog', buttons);
240 }
241
242 $timeout(init);
360aaa75
TO
243 });
244
70980d8e 245})(angular, CRM.$, CRM._);