Merge pull request #23964 from eileenmcnaughton/tpl_err
[civicrm-core.git] / ang / crmMailingAB / services.js
1 (function (angular, $, _) {
2
3 function OptionGroup(values) {
4 this.get = function get(value) {
5 var r = _.where(values, {value: '' + value});
6 return r.length > 0 ? r[0] : null;
7 };
8 this.getByName = function get(name) {
9 var r = _.where(values, {name: '' + name});
10 return r.length > 0 ? r[0] : null;
11 };
12 this.getAll = function getAll() {
13 return values;
14 };
15 }
16
17 angular.module('crmMailingAB').factory('crmMailingABCriteria', function () {
18 // TODO Get data from server
19 var values = {
20 '1': {value: 'subject', name: 'subject', label: ts('Test different "Subject" lines')},
21 '2': {value: 'from', name: 'from', label: ts('Test different "From" lines')},
22 '3': {value: 'full_email', name: 'full_email', label: ts('Test entirely different emails')}
23 };
24 return new OptionGroup(values);
25 });
26
27 angular.module('crmMailingAB').factory('crmMailingABStatus', function () {
28 // TODO Get data from server
29 var values = {
30 '1': {value: '1', name: 'Draft', label: ts('Draft')},
31 '2': {value: '2', name: 'Testing', label: ts('Testing')},
32 '3': {value: '3', name: 'Final', label: ts('Final')}
33 };
34 return new OptionGroup(values);
35 });
36
37 // CrmMailingAB is a data-model which combines an AB test (APIv3 "MailingAB"), three mailings (APIv3 "Mailing"),
38 // and three sets of attachments (APIv3 "Attachment").
39 //
40 // example:
41 // var abtest = new CrmMailingAB(123);
42 // abtest.load().then(function(){
43 // alert("Mailing A is named "+abtest.mailings.a.name);
44 // });
45 angular.module('crmMailingAB').factory('CrmMailingAB', function (crmApi, crmMailingMgr, $q, CrmAttachments) {
46 function CrmMailingAB(id) {
47 this.id = id;
48 this.mailings = {};
49 this.attachments = {};
50 }
51
52 angular.extend(CrmMailingAB.prototype, {
53 getAutosaveSignature: function() {
54 //modified date is unset so that it gets ignored in comparison
55 //its value is overwritten with the save response from the server and may differ from the local value,
56 //which would result in an unnecessary auto-save
57 var mailings = angular.copy(this.mailings);
58 _.each(mailings, function(mailing) {
59 mailing.modified_date = undefined;
60 });
61 return [
62 this.ab,
63 mailings,
64 this.attachments.a.getAutosaveSignature(),
65 this.attachments.b.getAutosaveSignature(),
66 this.attachments.c.getAutosaveSignature()
67 ];
68 },
69 // @return Promise CrmMailingAB
70 load: function load() {
71 var crmMailingAB = this;
72 if (!crmMailingAB.id) {
73 crmMailingAB.ab = {
74 name: '',
75 status: 'Draft',
76 mailing_id_a: null,
77 mailing_id_b: null,
78 mailing_id_c: null,
79 testing_criteria: 'subject',
80 winner_criteria: null,
81 specific_url: '',
82 declare_winning_time: null,
83 group_percentage: 10
84 };
85 var mailingDefaults = {
86 // Most defaults provided by Mailing.create API, but we
87 // want to force-enable tracking.
88 open_tracking: "1",
89 url_tracking: "1",
90 mailing_type:"experiment"
91 };
92 crmMailingAB.mailings.a = crmMailingMgr.create(mailingDefaults);
93 crmMailingAB.mailings.b = crmMailingMgr.create(mailingDefaults);
94 mailingDefaults.mailing_type = 'winner';
95 crmMailingAB.mailings.c = crmMailingMgr.create(mailingDefaults);
96 crmMailingAB.attachments.a = new CrmAttachments(function () {
97 return {entity_table: 'civicrm_mailing', entity_id: crmMailingAB.ab.mailing_id_a};
98 });
99 crmMailingAB.attachments.b = new CrmAttachments(function () {
100 return {entity_table: 'civicrm_mailing', entity_id: crmMailingAB.ab.mailing_id_b};
101 });
102 crmMailingAB.attachments.c = new CrmAttachments(function () {
103 return {entity_table: 'civicrm_mailing', entity_id: crmMailingAB.ab.mailing_id_c};
104 });
105
106 var dfr = $q.defer();
107 dfr.resolve(crmMailingAB);
108 return dfr.promise;
109 }
110 else {
111 return crmApi('MailingAB', 'get', {id: crmMailingAB.id})
112 .then(function (abResult) {
113 if (abResult.count != 1) {
114 throw "Failed to load AB Test";
115 }
116 crmMailingAB.ab = abResult.values[abResult.id];
117 return crmMailingAB._loadMailings();
118 });
119 }
120 },
121 // @return Promise CrmMailingAB
122 save: function save() {
123 var crmMailingAB = this;
124 return crmMailingAB._saveMailings()
125 .then(function () {
126 return crmApi('MailingAB', 'create', crmMailingAB.ab)
127 .then(function (abResult) {
128 if (!crmMailingAB.id) {
129 crmMailingAB.id = crmMailingAB.ab.id = abResult.id;
130 }
131 });
132 })
133 .then(function () {
134 return crmMailingAB;
135 });
136 },
137 // Schedule the test
138 // @return Promise CrmMailingAB
139 // Note: Submission may cause the server state to change. Consider abtest.submit().then(...abtest.load()...)
140 submitTest: function submitTest() {
141 var crmMailingAB = this;
142 var params = {
143 id: this.ab.id,
144 status: 'Testing',
145 approval_date: 'now',
146 scheduled_date: this.mailings.a.scheduled_date ? this.mailings.a.scheduled_date : 'now'
147 };
148 return crmApi('MailingAB', 'submit', params)
149 .then(function () {
150 return crmMailingAB.load();
151 });
152 },
153 // Schedule the final mailing
154 // @return Promise CrmMailingAB
155 // Note: Submission may cause the server state to change. Consider abtest.submit().then(...abtest.load()...)
156 submitFinal: function submitFinal(winner_id) {
157 var crmMailingAB = this;
158 var params = {
159 id: this.ab.id,
160 status: 'Final',
161 winner_id: winner_id,
162 approval_date: 'now',
163 scheduled_date: this.mailings.c.scheduled_date ? this.mailings.c.scheduled_date : 'now'
164 };
165 return crmApi('MailingAB', 'submit', params)
166 .then(function () {
167 return crmMailingAB.load();
168 });
169 },
170 // @param mailing Object (per APIv3)
171 // @return Promise
172 'delete': function () {
173 if (this.id) {
174 return crmApi('MailingAB', 'delete', {id: this.id});
175 }
176 else {
177 var d = $q.defer();
178 d.resolve();
179 return d.promise;
180 }
181 },
182 // Load mailings A, B, and C (if available)
183 // @return Promise CrmMailingAB
184 _loadMailings: function _loadMailings() {
185 var crmMailingAB = this;
186 var todos = {};
187 _.each(['a', 'b', 'c'], function (mkey) {
188 if (crmMailingAB.ab['mailing_id_' + mkey]) {
189 todos[mkey] = crmMailingMgr.get(crmMailingAB.ab['mailing_id_' + mkey])
190 .then(function (mailing) {
191 crmMailingAB.mailings[mkey] = mailing;
192 crmMailingAB.attachments[mkey] = new CrmAttachments(function () {
193 return {entity_table: 'civicrm_mailing', entity_id: crmMailingAB.ab['mailing_id_' + mkey]};
194 });
195 return crmMailingAB.attachments[mkey].load();
196 });
197 }
198 else {
199 crmMailingAB.mailings[mkey] = crmMailingMgr.create();
200 crmMailingAB.attachments[mkey] = new CrmAttachments(function () {
201 return {entity_table: 'civicrm_mailing', entity_id: crmMailingAB.ab['mailing_id_' + mkey]};
202 });
203 }
204 });
205 return $q.all(todos).then(function () {
206 return crmMailingAB;
207 });
208 },
209 // Save mailings A, B, and C (if available)
210 // @return Promise CrmMailingAB
211 _saveMailings: function _saveMailings() {
212 var crmMailingAB = this;
213 var todos = {};
214 var p = $q.when(true);
215 _.each(['a', 'b', 'c'], function (mkey) {
216 if (!crmMailingAB.mailings[mkey]) {
217 return;
218 }
219 if (crmMailingAB.ab['mailing_id_' + mkey]) {
220 // paranoia: in case caller forgot to manage id on mailing
221 crmMailingAB.mailings[mkey].id = crmMailingAB.ab['mailing_id_' + mkey];
222 }
223 p = p.then(function(){
224 return crmMailingMgr.save(crmMailingAB.mailings[mkey])
225 .then(function () {
226 crmMailingAB.ab['mailing_id_' + mkey] = crmMailingAB.mailings[mkey].id;
227 return crmMailingAB.attachments[mkey].save();
228 });
229 });
230 });
231 return p.then(function () {
232 return crmMailingAB;
233 });
234 }
235
236 });
237 return CrmMailingAB;
238 });
239
240 })(angular, CRM.$, CRM._);