Merge pull request #4819 from eileenmcnaughton/CRM-15680
[civicrm-core.git] / js / angular-crm-util.js
1 /// crmUi: Sundry UI helpers
2 (function (angular, $, _) {
3 angular.module('crmUtil', []);
4
5 angular.module('crmUtil').factory('crmApi', function($q) {
6 return function(entity, action, params, message) {
7 // JSON serialization in CRM.api3 is not aware of Angular metadata like $$hash, so use angular.toJson()
8 var deferred = $q.defer();
9 var p;
10 if (_.isObject(entity)) {
11 p = CRM.api3(eval('('+angular.toJson(entity)+')'), message);
12 } else {
13 p = CRM.api3(entity, action, eval('('+angular.toJson(params)+')'), message);
14 }
15 // CRM.api3 returns a promise, but the promise doesn't really represent errors as errors, so we
16 // convert them
17 p.then(
18 function(result) {
19 if (result.is_error) {
20 deferred.reject(result);
21 } else {
22 deferred.resolve(result);
23 }
24 },
25 function(error) {
26 deferred.reject(error);
27 }
28 );
29 return deferred.promise;
30 };
31 });
32
33 angular.module('crmUtil').factory('crmLegacy', function() {
34 return CRM;
35 });
36
37 // example: scope.$watch('foo', crmLog.wrap(function(newValue, oldValue){ ... }));
38 angular.module('crmUtil').factory('crmLog', function(){
39 var level = 0;
40 var write = console.log;
41 function indent() {
42 var s = '>';
43 for (var i = 0; i < level; i++) s = s + ' ';
44 return s;
45 }
46 var crmLog = {
47 log: function(msg, vars) {
48 write(indent() + msg, vars);
49 },
50 wrap: function(label, f) {
51 return function(){
52 level++;
53 crmLog.log(label + ": start", arguments);
54 var r;
55 try {
56 r = f.apply(this, arguments);
57 } finally {
58 crmLog.log(label + ": end");
59 level--;
60 }
61 return r;
62 }
63 }
64 };
65 return crmLog;
66 });
67
68 angular.module('crmUtil').factory('crmNavigator', ['$window', function($window) {
69 return {
70 redirect: function(path) {
71 $window.location.href = path;
72 }
73 };
74 }]);
75
76 angular.module('crmUtil').factory('crmNow', function($q){
77 // FIXME: surely there's already some helper which can do this in one line?
78 // @return string "YYYY-MM-DD hh:mm:ss"
79 return function crmNow() {
80 var currentdate = new Date();
81 var yyyy = currentdate.getFullYear();
82 var mm = currentdate.getMonth() + 1;
83 mm = mm < 10 ? '0' + mm : mm;
84 var dd = currentdate.getDate();
85 dd = dd < 10 ? '0' + dd : dd;
86 var hh = currentdate.getHours();
87 hh = hh < 10 ? '0' + hh : hh;
88 var min = currentdate.getMinutes();
89 min = min < 10 ? '0' + min : min;
90 var sec = currentdate.getSeconds();
91 sec = sec < 10 ? '0' + sec : sec;
92 return yyyy + "-" + mm + "-" + dd + " " + hh + ":" + min + ":" + sec;
93 };
94 });
95
96 // Adapter for CRM.status which supports Angular promises (instead of jQuery promises)
97 // example: crmStatus('Saving', crmApi(...)).then(function(result){...})
98 angular.module('crmUtil').factory('crmStatus', function($q){
99 return function(options, aPromise){
100 return CRM.toAPromise($q, CRM.status(options, CRM.toJqPromise(aPromise)));
101 };
102 });
103
104 // crmWatcher allows one to setup event listeners and temporarily suspend
105 // them en masse.
106 //
107 // example:
108 // angular.controller(... function($scope, crmWatcher){
109 // var watcher = crmWatcher();
110 // function myfunc() {
111 // watcher.suspend('foo', function(){
112 // ...do stuff...
113 // });
114 // }
115 // watcher.setup('foo', function(){
116 // return [
117 // $scope.$watch('foo', myfunc),
118 // $scope.$watch('bar', myfunc),
119 // $scope.$watch('whiz', otherfunc)
120 // ];
121 // });
122 // });
123 angular.module('crmUtil').factory('crmWatcher', function(){
124 return function() {
125 var unwatches = {}, watchFactories = {}, suspends = {};
126
127 // Specify the list of watches
128 this.setup = function(name, newWatchFactory) {
129 watchFactories[name] = newWatchFactory;
130 unwatches[name] = watchFactories[name]();
131 suspends[name] = 0;
132 return this;
133 };
134
135 // Temporarily disable watches and run some logic
136 this.suspend = function(name, f) {
137 suspends[name]++;
138 this.teardown(name);
139 var r;
140 try {
141 r = f.apply(this, []);
142 } finally {
143 if (suspends[name] === 1) {
144 unwatches[name] = watchFactories[name]();
145 if (!angular.isArray(unwatches[name])) {
146 unwatches[name] = [unwatches[name]];
147 }
148 }
149 suspends[name]--;
150 }
151 return r;
152 };
153
154 this.teardown = function(name) {
155 if (!unwatches[name]) return;
156 _.each(unwatches[name], function(unwatch){
157 unwatch();
158 });
159 delete unwatches[name];
160 };
161
162 return this;
163 }
164 });
165
166 })(angular, CRM.$, CRM._);