Merge remote-tracking branch 'upstream/4.5' into 4.5-4.6-2015-03-16-17-24-33
[civicrm-core.git] / js / angular-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, crmNow) {
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 return [
55 this.ab,
56 this.mailings,
57 this.attachments.a.getAutosaveSignature(),
58 this.attachments.b.getAutosaveSignature(),
59 this.attachments.c.getAutosaveSignature()
60 ];
61 },
62 // @return Promise CrmMailingAB
63 load: function load() {
64 var crmMailingAB = this;
65 if (!crmMailingAB.id) {
66 crmMailingAB.ab = {
67 name: '',
68 status: 'Draft',
69 mailing_id_a: null,
70 mailing_id_b: null,
71 mailing_id_c: null,
72 domain_id: null,
73 testing_criteria: 'subject',
74 winner_criteria: null,
75 specific_url: '',
76 declare_winning_time: null,
77 group_percentage: 10
78 };
79 var mailingDefaults = {
80 // Most defaults provided by Mailing.create API, but we
81 // want to force-enable tracking.
82 open_tracking: "1",
83 url_tracking: "1",
84 mailing_type:"experiment"
85 };
86 crmMailingAB.mailings.a = crmMailingMgr.create(mailingDefaults);
87 crmMailingAB.mailings.b = crmMailingMgr.create(mailingDefaults);
88 mailingDefaults.mailing_type = 'winner';
89 crmMailingAB.mailings.c = crmMailingMgr.create(mailingDefaults);
90 crmMailingAB.attachments.a = new CrmAttachments(function () {
91 return {entity_table: 'civicrm_mailing', entity_id: crmMailingAB.ab.mailing_id_a};
92 });
93 crmMailingAB.attachments.b = new CrmAttachments(function () {
94 return {entity_table: 'civicrm_mailing', entity_id: crmMailingAB.ab.mailing_id_b};
95 });
96 crmMailingAB.attachments.c = new CrmAttachments(function () {
97 return {entity_table: 'civicrm_mailing', entity_id: crmMailingAB.ab.mailing_id_c};
98 });
99
100 var dfr = $q.defer();
101 dfr.resolve(crmMailingAB);
102 return dfr.promise;
103 }
104 else {
105 return crmApi('MailingAB', 'get', {id: crmMailingAB.id})
106 .then(function (abResult) {
107 if (abResult.count != 1) {
108 throw "Failed to load AB Test";
109 }
110 crmMailingAB.ab = abResult.values[abResult.id];
111 return crmMailingAB._loadMailings();
112 });
113 }
114 },
115 // @return Promise CrmMailingAB
116 save: function save() {
117 var crmMailingAB = this;
118 return crmMailingAB._saveMailings()
119 .then(function () {
120 return crmApi('MailingAB', 'create', crmMailingAB.ab)
121 .then(function (abResult) {
122 if (!crmMailingAB.id) {
123 crmMailingAB.id = crmMailingAB.ab.id = abResult.id;
124 }
125 });
126 })
127 .then(function () {
128 return crmMailingAB;
129 });
130 },
131 // Schedule the test
132 // @return Promise CrmMailingAB
133 // Note: Submission may cause the server state to change. Consider abtest.submit().then(...abtest.load()...)
134 submitTest: function submitTest() {
135 var crmMailingAB = this;
136 var params = {
137 id: this.ab.id,
138 status: 'Testing',
139 approval_date: crmNow(),
140 scheduled_date: this.mailings.a.scheduled_date ? this.mailings.a.scheduled_date : crmNow()
141 };
142 return crmApi('MailingAB', 'submit', params)
143 .then(function () {
144 return crmMailingAB.load();
145 });
146 },
147 // Schedule the final mailing
148 // @return Promise CrmMailingAB
149 // Note: Submission may cause the server state to change. Consider abtest.submit().then(...abtest.load()...)
150 submitFinal: function submitFinal() {
151 var crmMailingAB = this;
152 var params = {
153 id: this.ab.id,
154 status: 'Final',
155 approval_date: crmNow(),
156 scheduled_date: this.mailings.c.scheduled_date ? this.mailings.c.scheduled_date : crmNow()
157 };
158 return crmApi('MailingAB', 'submit', params)
159 .then(function () {
160 return crmMailingAB.load();
161 });
162 },
163 // @param mailing Object (per APIv3)
164 // @return Promise
165 'delete': function () {
166 if (this.id) {
167 return crmApi('MailingAB', 'delete', {id: this.id});
168 }
169 else {
170 var d = $q.defer();
171 d.resolve();
172 return d.promise;
173 }
174 },
175 // Load mailings A, B, and C (if available)
176 // @return Promise CrmMailingAB
177 _loadMailings: function _loadMailings() {
178 var crmMailingAB = this;
179 var todos = {};
180 _.each(['a', 'b', 'c'], function (mkey) {
181 if (crmMailingAB.ab['mailing_id_' + mkey]) {
182 todos[mkey] = crmMailingMgr.get(crmMailingAB.ab['mailing_id_' + mkey])
183 .then(function (mailing) {
184 crmMailingAB.mailings[mkey] = mailing;
185 crmMailingAB.attachments[mkey] = new CrmAttachments(function () {
186 return {entity_table: 'civicrm_mailing', entity_id: crmMailingAB.ab['mailing_id_' + mkey]};
187 });
188 return crmMailingAB.attachments[mkey].load();
189 });
190 }
191 else {
192 crmMailingAB.mailings[mkey] = crmMailingMgr.create();
193 crmMailingAB.attachments[mkey] = new CrmAttachments(function () {
194 return {entity_table: 'civicrm_mailing', entity_id: crmMailingAB.ab['mailing_id_' + mkey]};
195 });
196 }
197 });
198 return $q.all(todos).then(function () {
199 return crmMailingAB;
200 });
201 },
202 // Save mailings A, B, and C (if available)
203 // @return Promise CrmMailingAB
204 _saveMailings: function _saveMailings() {
205 var crmMailingAB = this;
206 var todos = {};
207 var p = $q.when(true);
208 _.each(['a', 'b', 'c'], function (mkey) {
209 if (!crmMailingAB.mailings[mkey]) {
210 return;
211 }
212 if (crmMailingAB.ab['mailing_id_' + mkey]) {
213 // paranoia: in case caller forgot to manage id on mailing
214 crmMailingAB.mailings[mkey].id = crmMailingAB.ab['mailing_id_' + mkey];
215 }
216 p = p.then(function(){
217 return crmMailingMgr.save(crmMailingAB.mailings[mkey])
218 .then(function () {
219 crmMailingAB.ab['mailing_id_' + mkey] = crmMailingAB.mailings[mkey].id;
220 return crmMailingAB.attachments[mkey].save();
221 });
222 });
223 });
224 return p.then(function () {
225 return crmMailingAB;
226 });
227 }
228
229 });
230 return CrmMailingAB;
231 });
232
233 })(angular, CRM.$, CRM._);