add code comments
[civicrm-core.git] / js / angular-crmMailingAB.js
index 8fd19d283f3115e4acd738a1ed1295a29a86a107..63715dad16f083f8ee40df4f8f807fcf0f6b5097 100644 (file)
-/**
- * Created by aditya on 6/12/14.
- */
-
-
-(function(angular, $, _) {
-
-    var partialUrl = function(relPath) {
-        //console.log(CRM.resourceUrls['civicrm']);
-        //return CRM.resourceUrls['civicrm'] + '/partials/abtesting/' + relPath;
-        return '/drupal-7.28/sites/all/modules/civicrm/partials/abtesting/' + relPath;
-
-
-    };
-
-    var crmMailingAB = angular.module('crmMailingAB', ['ngRoute', 'ui.utils']);
-
-    crmMailingAB.run(function($rootScope, $templateCache) {
-        $rootScope.$on('$viewContentLoaded', function() {
-            $templateCache.removeAll();
-        });
-    });
-
-    crmMailingAB.config(['$routeProvider',
-        function($routeProvider) {
-            $routeProvider.when('/mailing', {
-                template: '<h1>sdfs</h1>',
-                controller: 'mailingListCtrl',
-                resolve: {
-                    mailingList: function($route, crmApi) {
-                        return crmApi('Mailing', 'get', {});
-                    }
-                }
-            });
-
-            $routeProvider.when('/mailing/abtesting', {
-                templateUrl: partialUrl('main.html'),
-                controller: 'TabsDemoCtrl',
-                resolve: {
-                    metaData: function($route, crmApi) {
-                        return crmApi('Group', 'get', {});
-                    },
-                    mailingList: function($route, crmApi) {
-                        return crmApi('Mailing', 'get', {});
-                    }
-                }
-            });
+(function (angular, $, _) {
+
+  var partialUrl = function (relPath, module) {
+    if (!module) {
+      module = 'crmMailingAB';
+    }
+    return CRM.resourceUrls.civicrm + '/partials/' + module + '/' + relPath;
+  };
+
+  angular.module('crmMailingAB', ['ngRoute', 'ui.utils', 'ngSanitize', 'crmUi', 'crmAttachment', 'crmMailing', 'crmD3']);
+  angular.module('crmMailingAB').config([
+    '$routeProvider',
+    function ($routeProvider) {
+      $routeProvider.when('/abtest', {
+        templateUrl: partialUrl('list.html'),
+        controller: 'CrmMailingABListCtrl',
+        resolve: {
+          mailingABList: function ($route, crmApi) {
+            return crmApi('MailingAB', 'get', {rowCount: 0});
+          }
         }
-    ]);
-//-----------------------------------------
-    // Add a new record by name.
-    // Ex: <crmAddName crm-options="['Alpha','Beta','Gamma']" crm-var="newItem" crm-on-add="callMyCreateFunction(newItem)" />
-
-    crmMailingAB.controller('TabsDemoCtrl', function($scope, crmApi, metaData, mailingList) {
-
-        $scope.groups = metaData.values;
-        $scope.mailings = mailingList.values;
-        $scope.tab_val=0;
-        $scope.max_tab=0;
-        $scope.campaign_clicked= function(){
-            if($scope.max_tab >= 0 ){
-                $scope.tab_val  =0;
-            }
-        };
-        $scope.compose_clicked=function(){
-            if($scope.max_tab >=1){
-                $scope.tab_val =1;
-            }
-        };
-        $scope.rec_clicked=function(){
-            if($scope.max_tab >=2){
-                $scope.tab_val =2;
-            }
-        };
-        $scope.preview_clicked=function(){
-            if($scope.max_tab>=3){
-                $scope.tab_val=3;
-            }
-        };
-        $scope.templates =
-            [   { name: 'Subject Lines', url: partialUrl('subject_lines.html')},
-                { name: 'From Name', url: partialUrl('from_name.html')},
-                {name:'Two different Emails',url: partialUrl('two_emails.html')} ];
-        $scope.template = $scope.templates[0];
-
-        $scope.slide_value = 0;
-
-        $scope.setifyes= function(val){
-            if(val ==1) {
-                $scope.ifyes = true;
-            }
-            else
-            $scope.ifyes=false;
-        };
-
-        $scope.send_date ="01/01/2000";
-
-        $scope.mailA={};
-
-        $scope.mailB={};
-        $scope.save=function(dat){
-
-            var result= crmApi('Mailing', 'create',dat, true);
-            console.log("Ac "+result);
-        };
-
-        $scope.init=function(par){
-
-            $scope.whatnext=par.toString()
+      });
+      $routeProvider.when('/abtest/:id', {
+        templateUrl: partialUrl('edit.html'),
+        controller: 'CrmMailingABEditCtrl',
+        resolve: {
+          abtest: function ($route, CrmMailingAB) {
+            var abtest = new CrmMailingAB($route.current.params.id == 'new' ? null : $route.current.params.id);
+            return abtest.load();
+          }
         }
+      });
+      $routeProvider.when('/abtest/:id/report', {
+        templateUrl: partialUrl('report.html'),
+        controller: 'CrmMailingABReportCtrl',
+        resolve: {
+          abtest: function ($route, CrmMailingAB) {
+            var abtest = new CrmMailingAB($route.current.params.id);
+            return abtest.load();
+          }
+        }
+      });
+    }
+  ]);
+
+  angular.module('crmMailingAB').controller('CrmMailingABListCtrl', function ($scope, mailingABList, crmMailingABCriteria, crmMailingABStatus) {
+    var ts = $scope.ts = CRM.ts('CiviMail');
+    $scope.mailingABList = mailingABList.values;
+    $scope.crmMailingABCriteria = crmMailingABCriteria;
+    $scope.crmMailingABStatus = crmMailingABStatus;
+  });
+
+  angular.module('crmMailingAB').controller('CrmMailingABEditCtrl', function ($scope, abtest, crmMailingABCriteria, crmMailingMgr, crmMailingPreviewMgr, crmStatus, $q, $location) {
+    $scope.abtest = abtest;
+    var ts = $scope.ts = CRM.ts('CiviMail');
+    $scope.crmMailingABCriteria = crmMailingABCriteria;
+    $scope.crmMailingConst = CRM.crmMailing;
+    $scope.partialUrl = partialUrl;
+
+    $scope.isSubmitted = function isSubmitted() {
+      return _.size(abtest.mailings.a.jobs) > 0 || _.size(abtest.mailings.b.jobs) > 0;
+    };
 
+    $scope.sync = function sync() {
+      abtest.mailings.a.name = ts('Test A (%1)', {1: abtest.ab.name});
+      abtest.mailings.b.name = ts('Test B (%1)', {1: abtest.ab.name});
+      abtest.mailings.c.name = ts('Winner (%1)', {1: abtest.ab.name});
+
+      var criteria = crmMailingABCriteria.get(abtest.ab.testing_criteria_id);
+      if (criteria) {
+        // TODO review fields exposed in UI and make sure the sync rules match
+        switch (criteria.name) {
+          case 'Subject lines':
+            crmMailingMgr.mergeInto(abtest.mailings.b, abtest.mailings.a, [
+              'name',
+              'groups',
+              'mailings',
+              'subject'
+            ]);
+            break;
+          case 'From names':
+            crmMailingMgr.mergeInto(abtest.mailings.b, abtest.mailings.a, [
+              'name',
+              'groups',
+              'mailings',
+              'from_name',
+              'from_email'
+            ]);
+            break;
+          case 'Two different emails':
+            crmMailingMgr.mergeInto(abtest.mailings.b, abtest.mailings.a, [
+              'name',
+              'groups',
+              'mailings',
+              'subject',
+              'from_name',
+              'from_email',
+              'body_html',
+              'body_text'
+            ]);
+            break;
+          default:
+            throw "Unrecognized testing_criteria";
+        }
+      }
+      crmMailingMgr.mergeInto(abtest.mailings.c, abtest.mailings.a, ['name']);
+      return $q.when(true);
+    };
 
-    });
-
-    crmMailingAB.directive('nexttab', function() {
-        return {
-            // Restrict it to be an attribute in this case
-            restrict: 'A',
-
-            priority: 500,
-            // responsible for registering DOM listeners as well as updating the DOM
-            link: function(scope, element, attrs) {
-
-                $(element).parent().parent().parent().parent().tabs(scope.$eval(attrs.nexttab));
-                var myarr = new Array(1,2,3)
-                $(element).parent().parent().parent().parent().tabs({disabled:myarr});
-
-                $(element).on("click",function() {
-                    scope.tab_val=scope.tab_val +1;
-
-                    scope.max_tab= Math.max(scope.tab_val,scope.max_tab);
-                    var myArray1 = new Array(  );
-                    for ( var i = scope.max_tab+1; i < 4; i++ ) {
-                        myArray1.push(i);
-                    }
-                    $(element).parent().parent().parent().parent().parent().tabs( "option", "disabled", myArray1 );
-                    $(element).parent().parent().parent().parent().parent().tabs("option", "active", scope.tab_val);
-                    scope.$apply();
-                    console.log("Adir");
-                });
-            }
-        };
-    });
-
-    crmMailingAB.directive('prevtab', function() {
-        return {
-            // Restrict it to be an attribute in this case
-            restrict: 'A',
-            priority: 500,
-            // responsible for registering DOM listeners as well as updating the DOM
-            link: function(scope, element, attrs) {
-
-
-
-                $(element).on("click",function() {
-                    var temp= scope.tab_val -1 ;
-                    scope.tab_val=scope.tab_val -1;
-
-                    console.log(temp);
-                    if(temp==3){
-
-                    }
-                    else {
-                        $(element).parent().parent().parent().parent().parent().tabs("option", "active", temp);
-                    }
-
-                    scope.$apply();
-
-                });
-            }
-        };
-    });
-
-    crmMailingAB.directive('groupselect',function(){
-       return {
-           restrict : 'AE',
-           link: function(scope,element, attrs){
-               $(element).select2({width:"400px",placeholder: "Select the groups you wish to include"});
-               $(element).select2("data",groups)
-           }
-       };
-
-    });
-
-    crmMailingAB.directive('sliderbar',function(){
-       return{
-           restrict: 'AE',
-           link: function(scope,element, attrs){
-               $(element).slider({min:1});
-               $(element).slider({
-                   slide: function( event, ui ) {
-                       scope.slide_value = ui.value;
-                       scope.$apply();
-                   }
-               });
-           }
-       };
-    });
-
-    crmMailingAB.directive('tpmax',function(){
-        return {
-            restrict: 'E',
-            link: function(scope,element,attr){
-                scope.$watch('automated', function(val) {
-                    if(val=="Yes") {
-                        $(element).dialog({
-                            title: 'Automated A/B Testing',
-                            width: 800,
-                            height: 600,
-                            closed: false,
-                            cache: false,
-                            modal: true
-                        });
-                    }
-                });
-
-                $(element).find("#closebutton").on("click",function(){
-                    $(element).dialog("close");
-                });
-            }
-        };
-    });
-
-    crmMailingAB.directive('numbar',function(){
-        return{
-            restrict: 'AE',
-            link: function(scope,element, attrs){
-                $(element).spinner({max:attrs.numbar,min:0});
-            }
-        };
-    });
-
-    crmMailingAB.directive('datepick',function(){
-        return {
-            scope :{
-                foo : '=send_date'
-            },
-          restrict: 'AE',
-          link: function(scope,element,attrs){
-                $(element).datepicker({
-                    onSelect: function(date) {
-                        $(".ui-datepicker a").removeAttr("href");
-                        scope.foo =date;
-                        console.log(date);
-                    }
-                });
-            }
-        };
-    });
-
-    crmMailingAB.directive('submitform',function(){
-        return {
-          restrict:'A',
-            priority: 1000,
-          link: function(scope,element,attrs){
-              $(element).on("click",function() {
-
-                  console.log("clicked");
-                  scope.save({
-                      "sequential": 1,
-                       "name": "Aditya Nambiar",
-                      "subject": scope.mailA.subj,
-                      "created_id": "2",
-                      "from_email": scope.mailA.fromEmail,
-                      "body_text": scope.mailA.body
-
-                  });
-                  console.log("Truth "+ scope.whatnext)
-
-                  if(scope.whatnext=="3"){
-                      console.log("sdf");
-                      scope.mailB.subj=scope.mailA.subj;
-                      scope.mailB.body=scope.mailA.body;
-
-                  }
-                  else if(scope.whatnext=="2"){
-                      scope.mailB.fromEmail=scope.mailA.fromEmail;
-                      scope.mailB.body=scope.mailA.body;
+    // @return Promise
+    $scope.save = function save() {
+      $scope.sync();
+      return crmStatus({start: ts('Saving...'), success: ts('Saved')}, abtest.save().then(updateUrl));
+    };
 
-                  }
-                  
+    // @return Promise
+    $scope.previewMailing = function previewMailing(mailingName, mode) {
+      $scope.sync();
+      return crmMailingPreviewMgr.preview(abtest.mailings[mailingName], mode);
+    };
 
-                  scope.save({
-                      "sequential": 1,
-                      "name": "Aditya Nambiar",
-                      "subject": scope.mailB.subj,
-                      "created_id": "2",
-                      "from_email": scope.mailB.fromEmail,
-                      "body_text": scope.mailB.body
+    // @return Promise
+    $scope.sendTest = function sendTest(mailingName, recipient) {
+      $scope.sync();
+      return crmStatus({start: ts('Saving...'), success: ''}, abtest.save().then(updateUrl))
+        .then(function () {
+          crmMailingPreviewMgr.sendTest(abtest.mailings[mailingName], recipient);
+        });
+    };
 
-                  });
+    // @return Promise
+    $scope.delete = function () {
+      return crmStatus({start: ts('Deleting...'), success: ts('Deleted')}, abtest.delete().then(leave));
+    };
 
-              });
-          }
-        };
+    // @return Promise
+    $scope.submit = function submit() {
+      $scope.sync();
+      return crmStatus({start: ts('Saving...'), success: ''}, abtest.save())
+        .then(function () {
+          return crmStatus({start: ts('Submitting...'), success: ts('Submitted')}, abtest.submitTest());
+          // Note: We're going to leave, so we don't care that submit() modifies several server-side records.
+          // If we stayed on this page, then we'd care about updating and call: abtest.submitTest().then(...abtest.load()...)
+        })
+        .then(leave);
+    };
 
+    function leave() {
+      $location.path('abtest');
+      $location.replace();
+    }
+
+    function updateCriteriaName() {
+      var criteria = crmMailingABCriteria.get($scope.abtest.ab.testing_criteria_id);
+      $scope.criteriaName = criteria ? criteria.name : null;
+    }
+
+    // Transition URL "/abtest/new" => "/abtest/123"
+    function updateUrl() {
+      var parts = $location.path().split('/'); // e.g. "/abtest/new" or "/abtest/123/wizard"
+      if (parts[2] != $scope.abtest.ab.id) {
+        parts[2] = $scope.abtest.ab.id;
+        $location.path(parts.join('/'));
+        $location.replace();
+        // FIXME: Angular unnecessarily refreshes UI
+        // WARNING: Changing the URL triggers a full reload. Any pending AJAX operations
+        // could be inconsistently applied. Run updateUrl() after other changes complete.
+      }
+    }
+
+    // initialize
+    updateCriteriaName();
+    $scope.sync();
+    $scope.$watch('abtest.ab.testing_criteria_id', updateCriteriaName);
+  });
+
+  angular.module('crmMailingAB').controller('CrmMailingABReportCtrl', function ($scope, abtest, crmApi, crmMailingPreviewMgr, dialogService) {
+    var ts = $scope.ts = CRM.ts('CiviMail');
+
+    $scope.abtest = abtest;
+
+    $scope.stats = {};
+    crmApi('Mailing', 'stats', {mailing_id: abtest.ab.mailing_id_a}).then(function(data){
+      $scope.stats.a = data.values[abtest.ab.mailing_id_a];
     });
-
-    crmMailingAB.directive('nextbutton',function(){
-        return {
-            restrict: 'AE',
-            replace:'true',
-            template:'<div class="crm-submit-buttons" id="campaignbutton">'+
-                '<div class = "crm-button crm-button-type-upload crm-button_qf_Contact_upload_view"   >' +
-                '<input type="submit" value="Next"  id="campaignbutton _qf_Contact_upload_view-top" class="btn btn-primary" nexttab={{tab_val}}>'+
-                '</div></div>'
-
-        };
+    crmApi('Mailing', 'stats', {mailing_id: abtest.ab.mailing_id_b}).then(function(data){
+      $scope.stats.b = data.values[abtest.ab.mailing_id_b];
     });
-
-    crmMailingAB.directive('prevbutton',function(){
-        return {
-            restrict: 'AE',
-            replace:'true',
-            template:'<div class="crm-submit-buttons" >'+
-                '<div class = "crm-button crm-button-type-upload crm-button_qf_Contact_upload_view"   >' +
-                '<input type="submit" value="Previous"  id="campaignbutton _qf_Contact_upload_view-top" class="btn btn-primary" prevtab={{tab_val}}>'+
-                '</div></div>'
-
-        };
+    crmApi('Mailing', 'stats', {mailing_id: abtest.ab.mailing_id_c}).then(function(data){
+      $scope.stats.c = data.values[abtest.ab.mailing_id_c];
     });
 
-
-
+    $scope.previewMailing = function previewMailing(mailingName, mode) {
+      return crmMailingPreviewMgr.preview(abtest.mailings[mailingName], mode);
+    };
+    $scope.selectWinner = function selectWinner(mailingName) {
+      var model = {
+        abtest: abtest,
+        mailingName: mailingName
+      };
+      var options = {
+        autoOpen: false,
+        modal: true,
+        title: ts('Select Winner (%1)', {
+          1: mailingName.toUpperCase()
+        })
+      };
+      return dialogService.open('selectWinnerDialog', partialUrl('selectWinner.html'), model, options);
+    };
+  });
+
+
+  angular.module('crmMailingAB').controller('CrmMailingABWinnerDialogCtrl', function ($scope, $timeout, dialogService, crmMailingMgr, crmStatus) {
+    var ts = $scope.ts = CRM.ts('CiviMail');
+    var abtest = $scope.abtest = $scope.model.abtest;
+    var mailingName = $scope.model.mailingName;
+
+    var titles = {a: ts('Mailing A'), b: ts('Mailing B')};
+    $scope.mailingTitle = titles[mailingName];
+
+    function init() {
+      // When using dialogService with a button bar, the major button actions
+      // need to be registered with the dialog widget (and not embedded in
+      // the body of the dialog).
+      var buttons = {};
+      buttons[ts('Select Winner')] = function () {
+        crmMailingMgr.mergeInto(abtest.mailings.c, abtest.mailings[mailingName], [
+          'name',
+          'groups',
+          'mailings',
+          'scheduled_date'
+        ]);
+        crmStatus({start: ts('Saving...'), success: ''}, abtest.save())
+          .then(function () {
+            return crmStatus({start: ts('Submitting...'), success: ts('Submitted')},
+              abtest.submitFinal().then(function(){
+                return abtest.load();
+              }));
+          })
+          .then(function(){
+            dialogService.close('selectWinnerDialog', abtest);
+          });
+      };
+      buttons[ts('Cancel')] = function () {
+        dialogService.cancel('selectWinnerDialog');
+      };
+      dialogService.setButtons('selectWinnerDialog', buttons);
+    }
+
+    $timeout(init);
+  });
 
 })(angular, CRM.$, CRM._);
-