(function (angular, $, _) { function OptionGroup(values) { this.get = function get(value) { var r = _.where(values, {value: '' + value}); return r.length > 0 ? r[0] : null; }; this.getByName = function get(name) { var r = _.where(values, {name: '' + name}); return r.length > 0 ? r[0] : null; }; this.getAll = function getAll() { return values; }; } angular.module('crmMailingAB').factory('crmMailingABCriteria', function () { // TODO Get data from server var values = { '1': {value: 'subject', name: 'subject', label: ts('Test different "Subject" lines')}, '2': {value: 'from', name: 'from', label: ts('Test different "From" lines')}, '3': {value: 'full_email', name: 'full_email', label: ts('Test entirely different emails')} }; return new OptionGroup(values); }); angular.module('crmMailingAB').factory('crmMailingABStatus', function () { // TODO Get data from server var values = { '1': {value: '1', name: 'Draft', label: ts('Draft')}, '2': {value: '2', name: 'Testing', label: ts('Testing')}, '3': {value: '3', name: 'Final', label: ts('Final')} }; return new OptionGroup(values); }); // CrmMailingAB is a data-model which combines an AB test (APIv3 "MailingAB"), three mailings (APIv3 "Mailing"), // and three sets of attachments (APIv3 "Attachment"). // // example: // var abtest = new CrmMailingAB(123); // abtest.load().then(function(){ // alert("Mailing A is named "+abtest.mailings.a.name); // }); angular.module('crmMailingAB').factory('CrmMailingAB', function (crmApi, crmMailingMgr, $q, CrmAttachments) { function CrmMailingAB(id) { this.id = id; this.mailings = {}; this.attachments = {}; } angular.extend(CrmMailingAB.prototype, { getAutosaveSignature: function() { return [ this.ab, this.mailings, this.attachments.a.getAutosaveSignature(), this.attachments.b.getAutosaveSignature(), this.attachments.c.getAutosaveSignature() ]; }, // @return Promise CrmMailingAB load: function load() { var crmMailingAB = this; if (!crmMailingAB.id) { crmMailingAB.ab = { name: '', status: 'Draft', mailing_id_a: null, mailing_id_b: null, mailing_id_c: null, domain_id: null, testing_criteria: 'subject', winner_criteria: null, specific_url: '', declare_winning_time: null, group_percentage: 10 }; var mailingDefaults = { // Most defaults provided by Mailing.create API, but we // want to force-enable tracking. open_tracking: "1", url_tracking: "1", mailing_type:"experiment" }; crmMailingAB.mailings.a = crmMailingMgr.create(mailingDefaults); crmMailingAB.mailings.b = crmMailingMgr.create(mailingDefaults); mailingDefaults.mailing_type = 'winner'; crmMailingAB.mailings.c = crmMailingMgr.create(mailingDefaults); crmMailingAB.attachments.a = new CrmAttachments(function () { return {entity_table: 'civicrm_mailing', entity_id: crmMailingAB.ab.mailing_id_a}; }); crmMailingAB.attachments.b = new CrmAttachments(function () { return {entity_table: 'civicrm_mailing', entity_id: crmMailingAB.ab.mailing_id_b}; }); crmMailingAB.attachments.c = new CrmAttachments(function () { return {entity_table: 'civicrm_mailing', entity_id: crmMailingAB.ab.mailing_id_c}; }); var dfr = $q.defer(); dfr.resolve(crmMailingAB); return dfr.promise; } else { return crmApi('MailingAB', 'get', {id: crmMailingAB.id}) .then(function (abResult) { if (abResult.count != 1) { throw "Failed to load AB Test"; } crmMailingAB.ab = abResult.values[abResult.id]; return crmMailingAB._loadMailings(); }); } }, // @return Promise CrmMailingAB save: function save() { var crmMailingAB = this; return crmMailingAB._saveMailings() .then(function () { return crmApi('MailingAB', 'create', crmMailingAB.ab) .then(function (abResult) { if (!crmMailingAB.id) { crmMailingAB.id = crmMailingAB.ab.id = abResult.id; } }); }) .then(function () { return crmMailingAB; }); }, // Schedule the test // @return Promise CrmMailingAB // Note: Submission may cause the server state to change. Consider abtest.submit().then(...abtest.load()...) submitTest: function submitTest() { var crmMailingAB = this; var params = { id: this.ab.id, status: 'Testing', approval_date: 'now', scheduled_date: this.mailings.a.scheduled_date ? this.mailings.a.scheduled_date : 'now' }; return crmApi('MailingAB', 'submit', params) .then(function () { return crmMailingAB.load(); }); }, // Schedule the final mailing // @return Promise CrmMailingAB // Note: Submission may cause the server state to change. Consider abtest.submit().then(...abtest.load()...) submitFinal: function submitFinal() { var crmMailingAB = this; var params = { id: this.ab.id, status: 'Final', approval_date: 'now', scheduled_date: this.mailings.c.scheduled_date ? this.mailings.c.scheduled_date : 'now' }; return crmApi('MailingAB', 'submit', params) .then(function () { return crmMailingAB.load(); }); }, // @param mailing Object (per APIv3) // @return Promise 'delete': function () { if (this.id) { return crmApi('MailingAB', 'delete', {id: this.id}); } else { var d = $q.defer(); d.resolve(); return d.promise; } }, // Load mailings A, B, and C (if available) // @return Promise CrmMailingAB _loadMailings: function _loadMailings() { var crmMailingAB = this; var todos = {}; _.each(['a', 'b', 'c'], function (mkey) { if (crmMailingAB.ab['mailing_id_' + mkey]) { todos[mkey] = crmMailingMgr.get(crmMailingAB.ab['mailing_id_' + mkey]) .then(function (mailing) { crmMailingAB.mailings[mkey] = mailing; crmMailingAB.attachments[mkey] = new CrmAttachments(function () { return {entity_table: 'civicrm_mailing', entity_id: crmMailingAB.ab['mailing_id_' + mkey]}; }); return crmMailingAB.attachments[mkey].load(); }); } else { crmMailingAB.mailings[mkey] = crmMailingMgr.create(); crmMailingAB.attachments[mkey] = new CrmAttachments(function () { return {entity_table: 'civicrm_mailing', entity_id: crmMailingAB.ab['mailing_id_' + mkey]}; }); } }); return $q.all(todos).then(function () { return crmMailingAB; }); }, // Save mailings A, B, and C (if available) // @return Promise CrmMailingAB _saveMailings: function _saveMailings() { var crmMailingAB = this; var todos = {}; var p = $q.when(true); _.each(['a', 'b', 'c'], function (mkey) { if (!crmMailingAB.mailings[mkey]) { return; } if (crmMailingAB.ab['mailing_id_' + mkey]) { // paranoia: in case caller forgot to manage id on mailing crmMailingAB.mailings[mkey].id = crmMailingAB.ab['mailing_id_' + mkey]; } p = p.then(function(){ return crmMailingMgr.save(crmMailingAB.mailings[mkey]) .then(function () { crmMailingAB.ab['mailing_id_' + mkey] = crmMailingAB.mailings[mkey].id; return crmMailingAB.attachments[mkey].save(); }); }); }); return p.then(function () { return crmMailingAB; }); } }); return CrmMailingAB; }); })(angular, CRM.$, CRM._);