Merge pull request #5239 from colemanw/ApiExplorer
[civicrm-core.git] / js / angular-crmMailingAB.js
1 (function (angular, $, _) {
2
3 angular.module('crmMailingAB', ['ngRoute', 'ui.utils', 'crmUi', 'crmAttachment', 'crmMailing', 'crmD3']);
4 angular.module('crmMailingAB').config([
5 '$routeProvider',
6 function ($routeProvider) {
7 $routeProvider.when('/abtest', {
8 templateUrl: '~/crmMailingAB/list.html',
9 controller: 'CrmMailingABListCtrl',
10 resolve: {
11 mailingABList: function ($route, crmApi) {
12 return crmApi('MailingAB', 'get', {rowCount: 0});
13 },
14 fields: function(crmMetadata){
15 return crmMetadata.getFields('MailingAB');
16 }
17 }
18 });
19 $routeProvider.when('/abtest/new', {
20 template: '<p>' + ts('Initializing...') + '</p>',
21 controller: 'CrmMailingABNewCtrl',
22 resolve: {
23 abtest: function ($route, CrmMailingAB) {
24 var abtest = new CrmMailingAB(null);
25 return abtest.load().then(function(){
26 return abtest.save();
27 });
28 }
29 }
30 });
31 $routeProvider.when('/abtest/:id', {
32 templateUrl: '~/crmMailingAB/main.html',
33 controller: 'CrmMailingABEditCtrl',
34 resolve: {
35 abtest: function ($route, CrmMailingAB) {
36 var abtest = new CrmMailingAB($route.current.params.id == 'new' ? null : $route.current.params.id);
37 return abtest.load();
38 }
39 }
40 });
41 }
42 ]);
43
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;
50 $scope.filter = {};
51 });
52
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"
56 parts[2] = abtest.id;
57 $location.path(parts.join('/'));
58 $location.replace();
59 });
60
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
70 $scope.isSubmitted = function isSubmitted() {
71 return _.size(abtest.mailings.a.jobs) > 0 || _.size(abtest.mailings.b.jobs) > 0;
72 };
73
74 $scope.sync = function sync() {
75 abtest.mailings.a.name = ts('Test A (%1)', {1: abtest.ab.name});
76 abtest.mailings.b.name = ts('Test B (%1)', {1: abtest.ab.name});
77 abtest.mailings.c.name = ts('Final (%1)', {1: abtest.ab.name});
78
79 if (abtest.ab.testing_criteria) {
80 // TODO review fields exposed in UI and make sure the sync rules match
81 switch (abtest.ab.testing_criteria) {
82 case 'subject':
83 crmMailingMgr.mergeInto(abtest.mailings.b, abtest.mailings.a, [
84 'name',
85 'recipients',
86 'subject'
87 ]);
88 break;
89 case 'from':
90 crmMailingMgr.mergeInto(abtest.mailings.b, abtest.mailings.a, [
91 'name',
92 'recipients',
93 'from_name',
94 'from_email'
95 ]);
96 break;
97 case 'full_email':
98 crmMailingMgr.mergeInto(abtest.mailings.b, abtest.mailings.a, [
99 'name',
100 'recipients',
101 'subject',
102 'from_name',
103 'from_email',
104 'replyto_email',
105 'override_verp', // keep override_verp and replyto_Email linked
106 'body_html',
107 'body_text'
108 ]);
109 break;
110 default:
111 throw "Unrecognized testing_criteria";
112 }
113 }
114 crmMailingMgr.mergeInto(abtest.mailings.c, abtest.mailings.a, ['name']);
115 return true;
116 };
117
118 // @return Promise
119 $scope.save = function save() {
120 return block(crmStatus({start: ts('Saving...'), success: ts('Saved')}, abtest.save()));
121 };
122
123 // @return Promise
124 $scope.previewMailing = function previewMailing(mailingName, mode) {
125 return crmMailingPreviewMgr.preview(abtest.mailings[mailingName], mode);
126 };
127
128 // @return Promise
129 $scope.sendTest = function sendTest(mailingName, recipient) {
130 return block(crmStatus({start: ts('Saving...'), success: ''}, abtest.save())
131 .then(function () {
132 crmMailingPreviewMgr.sendTest(abtest.mailings[mailingName], recipient);
133 }));
134 };
135
136 // @return Promise
137 $scope.delete = function () {
138 return block(crmStatus({start: ts('Deleting...'), success: ts('Deleted')}, abtest.delete().then($scope.leave)));
139 };
140
141 // @return Promise
142 $scope.submit = function submit() {
143 if (block.check() || $scope.crmMailingAB.$invalid) {
144 return;
145 }
146 return block(crmStatus({start: ts('Saving...'), success: ''}, abtest.save())
147 .then(function() {
148 return crmStatus({start: ts('Submitting...'), success: ts('Submitted')}, myAutosave.suspend(abtest.submitTest()));
149 // Note: We're going to leave, so we don't care that submit() modifies several server-side records.
150 // If we stayed on this page, then we'd care about updating and call: abtest.submitTest().then(...abtest.load()...)
151 })
152 );
153 };
154
155 $scope.leave = function leave() {
156 $location.path('abtest');
157 $location.replace();
158 };
159
160 $scope.selectWinner = function selectWinner(mailingName) {
161 var model = {
162 abtest: $scope.abtest,
163 mailingName: mailingName
164 };
165 var options = CRM.utils.adjustDialogDefaults({
166 autoOpen: false,
167 title: ts('Select Final Mailing (Test %1)', {
168 1: mailingName.toUpperCase()
169 })
170 });
171 return myAutosave.suspend(dialogService.open('selectWinnerDialog', '~/crmMailingAB/selectWinner.html', model, options));
172 };
173
174 // initialize
175 var syncJob = $interval($scope.sync, 333);
176 $scope.$on('$destroy', function(){
177 $interval.cancel(syncJob);
178 });
179
180 myAutosave = new CrmAutosaveCtrl({
181 save: $scope.save,
182 saveIf: function(){
183 return abtest.ab.status == 'Draft' && $scope.sync();
184 },
185 model: function(){
186 return abtest.getAutosaveSignature();
187 },
188 form: function() {
189 return $scope.crmMailingAB;
190 }
191 });
192 $timeout(myAutosave.start);
193 $scope.$on('$destroy', myAutosave.stop);
194 });
195
196 angular.module('crmMailingAB').controller('CrmMailingABReportCtrl', function ($scope, crmApi, crmMailingStats) {
197 var ts = $scope.ts = CRM.ts(null);
198
199 var CrmMailingABReportCnt = 1, activeMailings = null;
200 $scope.getActiveMailings = function() {
201 if ($scope.abtest.$CrmMailingABReportCnt != CrmMailingABReportCnt) {
202 $scope.abtest.$CrmMailingABReportCnt = ++CrmMailingABReportCnt;
203 activeMailings = [
204 {name: 'a', title: ts('Mailing A'), mailing: $scope.abtest.mailings.a, attachments: $scope.abtest.attachments.a},
205 {name: 'b', title: ts('Mailing B'), mailing: $scope.abtest.mailings.b, attachments: $scope.abtest.attachments.b}
206 ];
207 if ($scope.abtest.ab.status == 'Final') {
208 activeMailings.push({name: 'c', title: ts('Final'), mailing: $scope.abtest.mailings.c, attachments: $scope.abtest.attachments.c});
209 }
210 }
211 return activeMailings;
212 };
213
214 crmMailingStats.getStats({
215 a: $scope.abtest.ab.mailing_id_a,
216 b: $scope.abtest.ab.mailing_id_b,
217 c: $scope.abtest.ab.mailing_id_c
218 }).then(function(stats) {
219 $scope.stats = stats;
220 });
221
222 $scope.statTypes = crmMailingStats.getStatTypes();
223 $scope.statUrl = function statUrl(mailing, statType, view) {
224 return crmMailingStats.getUrl(mailing, statType, view, 'abtest/' + $scope.abtest.ab.id);
225 };
226
227 $scope.checkPerm = CRM.checkPerm;
228 });
229
230 angular.module('crmMailingAB').controller('CrmMailingABWinnerDialogCtrl', function ($scope, $timeout, dialogService, crmMailingMgr, crmStatus) {
231 var ts = $scope.ts = CRM.ts(null);
232 var abtest = $scope.abtest = $scope.model.abtest;
233 var mailingName = $scope.model.mailingName;
234
235 var titles = {a: ts('Mailing A'), b: ts('Mailing B')};
236 $scope.mailingTitle = titles[mailingName];
237
238 function init() {
239 // When using dialogService with a button bar, the major button actions
240 // need to be registered with the dialog widget (and not embedded in
241 // the body of the dialog).
242 var buttons = {};
243 buttons[ts('Submit final mailing')] = function () {
244 crmMailingMgr.mergeInto(abtest.mailings.c, abtest.mailings[mailingName], [
245 'name',
246 'recipients',
247 'scheduled_date'
248 ]);
249 crmStatus({start: ts('Saving...'), success: ''}, abtest.save())
250 .then(function () {
251 return crmStatus({start: ts('Submitting...'), success: ts('Submitted')},
252 abtest.submitFinal().then(function(r){
253 delete abtest.$CrmMailingABReportCnt;
254 return r;
255 }));
256 })
257 .then(function(){
258 dialogService.close('selectWinnerDialog', abtest);
259 });
260 };
261 buttons[ts('Cancel')] = function () {
262 dialogService.cancel('selectWinnerDialog');
263 };
264 dialogService.setButtons('selectWinnerDialog', buttons);
265 }
266
267 $timeout(init);
268 });
269
270 })(angular, CRM.$, CRM._);