faalis 0.26.3 → 1.0.0.alpha0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +35 -6
  3. data/Rakefile +2 -25
  4. data/app/assets/javascripts/faalis/angular-manifest.js +8 -2
  5. data/app/assets/javascripts/faalis/application.js +0 -3
  6. data/app/assets/javascripts/faalis/dashboard/application.js.erb +0 -5
  7. data/app/assets/javascripts/faalis/dashboard/functions.js.erb +9 -0
  8. data/app/assets/javascripts/faalis/dashboard/init.js +1 -1
  9. data/app/assets/javascripts/faalis/dashboard/modules/auth/group.js +0 -6
  10. data/app/assets/javascripts/faalis/dashboard/modules/fields/fields.js +1 -1
  11. data/app/assets/javascripts/faalis/dashboard/modules/fields/image.js +115 -0
  12. data/app/assets/javascripts/faalis/dashboard/modules/fields/tag.js +76 -0
  13. data/app/assets/javascripts/faalis/dashboard/variables.js.erb +1 -1
  14. data/app/assets/locale/templates.pot +282 -0
  15. data/app/assets/stylesheets/faalis/dashboard/dashboard.css.scss +4 -0
  16. data/app/assets/stylesheets/faalis/dashboard/ltr/application.css +4 -4
  17. data/app/assets/stylesheets/faalis/dashboard/rtl/application.css +4 -4
  18. data/app/assets/stylesheets/faalis/dashboard/rtl/base.css.scss.erb +2 -2
  19. data/app/controllers/faalis/api/v1/permissions_controller.rb +8 -39
  20. data/app/controllers/faalis/api/v1/users_controller.rb +7 -7
  21. data/app/models/ability.rb +4 -6
  22. data/app/models/faalis/concerns/assignment.rb +2 -2
  23. data/app/models/faalis/group.rb +18 -4
  24. data/app/models/faalis/permission.rb +11 -2
  25. data/app/models/faalis/permissions/auth.rb +3 -2
  26. data/app/models/faalis/user.rb +27 -73
  27. data/app/models/faalis/user/auth_definitions.rb +94 -0
  28. data/app/models/faalis/user/mongoid_fields.rb +76 -0
  29. data/app/models/faalis/user/permission.rb +21 -0
  30. data/app/views/angularjs_templates/auth/groups/new.html +0 -20
  31. data/app/views/angularjs_templates/fields/image/image.html +1 -0
  32. data/app/views/angularjs_templates/fields/relation/relation.html +3 -1
  33. data/app/views/angularjs_templates/fields/tag/tag.html +1 -0
  34. data/app/views/angularjs_templates/nav.html.erb +0 -1
  35. data/app/views/faalis/api/v1/users/index.json.jbuilder +1 -1
  36. data/app/views/layouts/faalis/application.html.erb +2 -0
  37. data/app/views/layouts/faalis/dashboard.html.erb +1 -0
  38. data/app/views/layouts/faalis/simple.html.erb +1 -0
  39. data/config/initializers/devise.rb +0 -7
  40. data/db/migrate/20131013091000_devise_create_faalis_users.rb +3 -2
  41. data/db/migrate/20140613120923_add_users_groups_table.rb +8 -0
  42. data/db/migrate/20140617124019_faalis_groups_users.rb +4 -0
  43. data/db/seeds.rb +39 -11
  44. data/lib/faalis.rb +5 -4
  45. data/lib/faalis/concerns.rb +7 -0
  46. data/lib/faalis/concerns/authorizable.rb +76 -0
  47. data/lib/faalis/discovery.rb +8 -0
  48. data/lib/faalis/discovery/permissions.rb +51 -0
  49. data/lib/faalis/engine.rb +19 -5
  50. data/lib/faalis/extensions.rb +18 -0
  51. data/lib/faalis/extensions/base.rb +29 -0
  52. data/lib/faalis/fake_assets.rb +7 -0
  53. data/lib/faalis/generators/dashboard_scaffold.rb +23 -5
  54. data/lib/faalis/omniauth.rb +3 -0
  55. data/lib/faalis/orm.rb +29 -0
  56. data/lib/faalis/{active_record.rb → patches/models.rb} +1 -3
  57. data/lib/faalis/version.rb +1 -1
  58. data/lib/generators/faalis/install_generator.rb +7 -3
  59. data/lib/{faalis/plugins.rb → generators/faalis/js/install_i18n_generator.rb} +20 -17
  60. data/lib/generators/faalis/scaffold_generator.rb +139 -0
  61. data/lib/generators/faalis/templates/application.js +1 -1
  62. data/lib/generators/faalis/templates/i18n/Gruntfile.js.erb +30 -0
  63. data/lib/generators/faalis/templates/i18n/README +13 -0
  64. data/lib/generators/faalis/templates/i18n/fa.js +3 -0
  65. data/lib/generators/faalis/templates/js/list_view/README +1 -1
  66. data/lib/tasks/faalis_tasks.rake +26 -20
  67. data/lib/tasks/grunt/Gruntfile.js +7 -2
  68. data/spec/dummy/config/initializers/faalis.rb +40 -0
  69. metadata +134 -44
  70. data/app/assets/javascripts/faalis/dashboard/lib/angular-gettext.js +0 -202
  71. data/app/assets/javascripts/faalis/dashboard/lib/ng-grid.js +0 -3260
  72. data/app/assets/javascripts/faalis/dashboard/lib/ng-quick-date.js +0 -297
  73. data/app/assets/javascripts/faalis/dashboard/lib/restangular.js +0 -1066
  74. data/app/assets/javascripts/faalis/dashboard/lib/select2.js +0 -3255
  75. data/app/assets/javascripts/faalis/dashboard/lib/ui.select2.js +0 -217
  76. data/app/assets/stylesheets/faalis/dashboard/ng-grid.css.scss +0 -442
  77. data/app/assets/stylesheets/faalis/dashboard/ng-quick-date-default-theme.css.scss +0 -20
  78. data/app/assets/stylesheets/faalis/dashboard/ng-quick-date.css.scss +0 -19
  79. data/app/assets/stylesheets/faalis/dashboard/select2.css.scss.erb +0 -618
  80. data/app/controllers/faalis/api/v1/#conversations_controller.rb# +0 -120
  81. data/app/models/faalis/workflow.rb +0 -4
  82. data/db/migrate/20140413180202_create_faalis_workflows.rb +0 -9
  83. data/lib/faalis/permissions.rb +0 -72
  84. data/lib/faalis/workflows.rb +0 -7
  85. data/lib/faalis/workflows/base.rb +0 -70
  86. data/lib/faalis/workflows/discovery.rb +0 -42
  87. data/lib/generators/faalis/js_scaffold_generator.rb +0 -113
@@ -1,297 +0,0 @@
1
- (function() {
2
- var app;
3
-
4
- app = angular.module("ngQuickDate", []);
5
-
6
- app.provider("ngQuickDateDefaults", function() {
7
- return {
8
- options: {
9
- dateFormat: 'M/d/yyyy',
10
- timeFormat: 'h:mm a',
11
- labelFormat: null,
12
- placeholder: 'Click to Set Date',
13
- hoverText: null,
14
- buttonIconHtml: null,
15
- closeButtonHtml: 'X',
16
- nextLinkHtml: 'Next',
17
- prevLinkHtml: 'Prev',
18
- disableTimepicker: false,
19
- disableClearButton: false,
20
- dayAbbreviations: ["Su", "M", "Tu", "W", "Th", "F", "Sa"],
21
- parseDateFunction: function(str) {
22
- var seconds;
23
- seconds = Date.parse(str);
24
- if (isNaN(seconds)) {
25
- return null;
26
- } else {
27
- return new Date(seconds);
28
- }
29
- }
30
- },
31
- $get: function() {
32
- return this.options;
33
- },
34
- set: function(keyOrHash, value) {
35
- var k, v, _results;
36
- if (typeof keyOrHash === 'object') {
37
- _results = [];
38
- for (k in keyOrHash) {
39
- v = keyOrHash[k];
40
- _results.push(this.options[k] = v);
41
- }
42
- return _results;
43
- } else {
44
- return this.options[keyOrHash] = value;
45
- }
46
- }
47
- };
48
- });
49
-
50
- app.directive("datepicker", [
51
- 'ngQuickDateDefaults', '$filter', '$sce', function(ngQuickDateDefaults, $filter, $sce) {
52
- return {
53
- restrict: "E",
54
- require: "ngModel",
55
- scope: {
56
- ngModel: "=",
57
- onChange: "&"
58
- },
59
- replace: true,
60
- link: function(scope, element, attrs, ngModel) {
61
- var dateToString, datepickerClicked, datesAreEqual, debug, getDaysInMonth, initialize, parseDateString, setCalendarDateFromModel, setCalendarRows, setConfigOptions, setInputDateFromModel;
62
- debug = attrs.debug && attrs.debug.length;
63
- initialize = function() {
64
- scope.toggleCalendar(false);
65
- scope.weeks = [];
66
- scope.inputDate = null;
67
- if (typeof scope.ngModel === 'string') {
68
- scope.ngModel = parseDateString(scope.ngModel);
69
- }
70
- setConfigOptions();
71
- setInputDateFromModel();
72
- return setCalendarDateFromModel();
73
- };
74
- setConfigOptions = function() {
75
- var key, value;
76
- for (key in ngQuickDateDefaults) {
77
- value = ngQuickDateDefaults[key];
78
- if (key.match(/[Hh]tml/)) {
79
- scope[key] = $sce.trustAsHtml(ngQuickDateDefaults[key] || "");
80
- } else if (attrs[key]) {
81
- scope[key] = attrs[key];
82
- } else {
83
- scope[key] = ngQuickDateDefaults[key];
84
- }
85
- }
86
- if (!scope.labelFormat) {
87
- scope.labelFormat = scope.dateFormat;
88
- if (!scope.disableTimepicker) {
89
- scope.labelFormat += " " + scope.timeFormat;
90
- }
91
- }
92
- if (attrs.iconClass && attrs.iconClass.length) {
93
- return scope.buttonIconHtml = $sce.trustAsHtml("<i ng-show='iconClass' class='" + attrs.iconClass + "'></i>");
94
- }
95
- };
96
- datepickerClicked = false;
97
- window.document.addEventListener('click', function(event) {
98
- if (!datepickerClicked) {
99
- scope.toggleCalendar(false);
100
- scope.$apply();
101
- }
102
- return datepickerClicked = false;
103
- });
104
- angular.element(element[0])[0].addEventListener('click', function(event) {
105
- return datepickerClicked = true;
106
- });
107
- setInputDateFromModel = function() {
108
- if (scope.ngModel) {
109
- scope.inputDate = $filter('date')(scope.ngModel, ngQuickDateDefaults.dateFormat);
110
- return scope.inputTime = $filter('date')(scope.ngModel, ngQuickDateDefaults.timeFormat);
111
- } else {
112
- scope.inputDate = null;
113
- return scope.inputTime = null;
114
- }
115
- };
116
- setCalendarDateFromModel = function() {
117
- var d;
118
- d = scope.ngModel ? new Date(scope.ngModel) : new Date();
119
- if (d.toString() === "Invalid Date") {
120
- d = new Date();
121
- }
122
- d.setDate(1);
123
- return scope.calendarDate = new Date(d);
124
- };
125
- setCalendarRows = function() {
126
- var curDate, d, day, daysInMonth, numRows, offset, row, selected, today, weeks, _i, _j, _ref;
127
- offset = scope.calendarDate.getDay();
128
- daysInMonth = getDaysInMonth(scope.calendarDate.getFullYear(), scope.calendarDate.getMonth());
129
- numRows = Math.ceil((offset + daysInMonth) / 7);
130
- weeks = [];
131
- curDate = new Date(scope.calendarDate);
132
- curDate.setDate(curDate.getDate() + (offset * -1));
133
- for (row = _i = 0, _ref = numRows - 1; 0 <= _ref ? _i <= _ref : _i >= _ref; row = 0 <= _ref ? ++_i : --_i) {
134
- weeks.push([]);
135
- for (day = _j = 0; _j <= 6; day = ++_j) {
136
- d = new Date(curDate);
137
- selected = scope.ngModel && d && datesAreEqual(d, scope.ngModel);
138
- today = datesAreEqual(d, new Date());
139
- weeks[row].push({
140
- date: d,
141
- selected: selected,
142
- other: d.getMonth() !== scope.calendarDate.getMonth(),
143
- today: today
144
- });
145
- curDate.setDate(curDate.getDate() + 1);
146
- }
147
- }
148
- return scope.weeks = weeks;
149
- };
150
- dateToString = function(date, format) {
151
- return $filter('date')(date, format);
152
- };
153
- parseDateString = ngQuickDateDefaults.parseDateFunction;
154
- datesAreEqual = function(d1, d2, compareTimes) {
155
- if (compareTimes == null) {
156
- compareTimes = false;
157
- }
158
- if (compareTimes) {
159
- return (d1 - d2) === 0;
160
- } else {
161
- return d1 && d2 && (d1.getYear() === d2.getYear()) && (d1.getMonth() === d2.getMonth()) && (d1.getDate() === d2.getDate());
162
- }
163
- };
164
- getDaysInMonth = function(year, month) {
165
- return [31, ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0 ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
166
- };
167
- scope.$watch('ngModel', function(newVal, oldVal) {
168
- if (newVal !== oldVal) {
169
- setInputDateFromModel();
170
- return setCalendarDateFromModel();
171
- }
172
- });
173
- scope.$watch('calendarDate', function(newVal, oldVal) {
174
- if (newVal !== oldVal) {
175
- return setCalendarRows();
176
- }
177
- });
178
- scope.$watch('calendarShown', function(newVal, oldVal) {
179
- var dateInput;
180
- dateInput = angular.element(element[0].querySelector(".quickdate-date-input"))[0];
181
- return dateInput.select();
182
- });
183
- scope.mainButtonStr = function() {
184
- if (scope.ngModel) {
185
- return $filter('date')(scope.ngModel, scope.labelFormat);
186
- } else {
187
- return scope.placeholder;
188
- }
189
- };
190
- scope.toggleCalendar = function(show) {
191
- if (isFinite(show)) {
192
- return scope.calendarShown = show;
193
- } else {
194
- return scope.calendarShown = !scope.calendarShown;
195
- }
196
- };
197
- scope.setDate = function(date, closeCalendar) {
198
- var changed;
199
- if (closeCalendar == null) {
200
- closeCalendar = true;
201
- }
202
- changed = (!scope.ngModel && date) || (scope.ngModel && !date) || (date.getTime() !== scope.ngModel.getTime());
203
- scope.ngModel = date;
204
- if (closeCalendar) {
205
- scope.toggleCalendar(false);
206
- }
207
- if (changed && scope.onChange) {
208
- return scope.onChange();
209
- }
210
- };
211
- scope.setDateFromInput = function(closeCalendar) {
212
- var err, tmpDate, tmpDateAndTime, tmpTime;
213
- if (closeCalendar == null) {
214
- closeCalendar = false;
215
- }
216
- try {
217
- tmpDate = parseDateString(scope.inputDate);
218
- if (!tmpDate) {
219
- throw 'Invalid Date';
220
- }
221
- if (!scope.disableTimepicker && scope.inputTime && scope.inputTime.length && tmpDate) {
222
- tmpTime = scope.disableTimepicker ? '00:00:00' : scope.inputTime;
223
- tmpDateAndTime = parseDateString("" + scope.inputDate + " " + tmpTime);
224
- if (!tmpDateAndTime) {
225
- throw 'Invalid Time';
226
- }
227
- scope.setDate(tmpDateAndTime, false);
228
- } else {
229
- scope.setDate(tmpDate, false);
230
- }
231
- if (closeCalendar) {
232
- scope.toggleCalendar(false);
233
- }
234
- scope.inputDateErr = false;
235
- return scope.inputTimeErr = false;
236
- } catch (_error) {
237
- err = _error;
238
- if (err === 'Invalid Date') {
239
- return scope.inputDateErr = true;
240
- } else if (err === 'Invalid Time') {
241
- return scope.inputTimeErr = true;
242
- }
243
- }
244
- };
245
- scope.onDateInputTab = function(param) {
246
- if (scope.disableTimepicker) {
247
- scope.toggleCalendar(false);
248
- }
249
- return true;
250
- };
251
- scope.onTimeInputTab = function(param) {
252
- scope.toggleCalendar(false);
253
- return true;
254
- };
255
- scope.nextMonth = function() {
256
- return scope.calendarDate = new Date(new Date(scope.calendarDate).setMonth(scope.calendarDate.getMonth() + 1));
257
- };
258
- scope.prevMonth = function() {
259
- return scope.calendarDate = new Date(new Date(scope.calendarDate).setMonth(scope.calendarDate.getMonth() - 1));
260
- };
261
- scope.clear = function() {
262
- scope.ngModel = null;
263
- return scope.toggleCalendar(false);
264
- };
265
- initialize();
266
- setCalendarRows();
267
- if (debug) {
268
- return console.log("quick date scope:", scope);
269
- }
270
- },
271
- template: "<div class='quickdate'>\n <a href='' ng-focus='toggleCalendar(true)' ng-click='toggleCalendar()' class='quickdate-button' title='{{hoverText}}'><div ng-hide='iconClass' ng-bind-html='buttonIconHtml'></div>{{mainButtonStr()}}</a>\n <div class='quickdate-popup' ng-class='{open: calendarShown}'>\n <a href='' tabindex='-1' class='quickdate-close' ng-click='toggleCalendar()'><div ng-bind-html='closeButtonHtml'></div></a>\n <div class='quickdate-text-inputs'>\n <div class='quickdate-input-wrapper'>\n <label>Date</label>\n <input class='quickdate-date-input' name='inputDate' type='text' ng-model='inputDate' placeholder='1/1/2013' ng-blur=\"setDateFromInput()\" ng-enter=\"setDateFromInput(true)\" ng-class=\"{'ng-quick-date-error': inputDateErr}\" ng-tab='onDateInputTab()' />\n </div>\n <div class='quickdate-input-wrapper' ng-hide='disableTimepicker'>\n <label>Time</label>\n <input class='quickdate-time-input' name='inputTime' type='text' ng-model='inputTime' placeholder='12:00 PM' ng-blur=\"setDateFromInput(false)\" ng-enter=\"setDateFromInput(true)\" ng-class=\"{'quickdate-error': inputTimeErr}\" ng-tab='onTimeInputTab()'>\n </div>\n </div>\n <div class='quickdate-calendar-header'>\n <a href='' class='quickdate-prev-month quickdate-action-link' tabindex='-1' ng-click='prevMonth()'><div ng-bind-html='prevLinkHtml'></div></a>\n <span class='quickdate-month'>{{calendarDate | date:'MMMM yyyy'}}</span>\n <a href='' class='quickdate-next-month quickdate-action-link' ng-click='nextMonth()' tabindex='-1' ><div ng-bind-html='nextLinkHtml'></div></a>\n </div>\n <table class='quickdate-calendar'>\n <thead>\n <tr>\n <th ng-repeat='day in dayAbbreviations'>{{day}}</th>\n </tr>\n </thead>\n <tbody>\n <tr ng-repeat='week in weeks'>\n <td ng-mousedown='setDate(day.date)' ng-class='{\"other-month\": day.other, \"selected\": day.selected, \"is-today\": day.today}' ng-repeat='day in week'>{{day.date | date:'d'}}</td>\n </tr>\n </tbody>\n </table>\n <div class='quickdate-popup-footer'>\n <a href='' class='quickdate-clear' tabindex='-1' ng-hide='disableClearButton' ng-click='clear()'>Clear</a>\n </div>\n </div>\n</div>"
272
- };
273
- }
274
- ]);
275
-
276
- app.directive('ngEnter', function() {
277
- return function(scope, element, attr) {
278
- return element.bind('keydown keypress', function(e) {
279
- if (e.which === 13) {
280
- scope.$apply(attr.ngEnter);
281
- return e.preventDefault();
282
- }
283
- });
284
- };
285
- });
286
-
287
- app.directive('ngTab', function() {
288
- return function(scope, element, attr) {
289
- return element.bind('keydown keypress', function(e) {
290
- if (e.which === 9) {
291
- return scope.$apply(attr.ngTab);
292
- }
293
- });
294
- };
295
- });
296
-
297
- }).call(this);
@@ -1,1066 +0,0 @@
1
- (function() {
2
-
3
- var module = angular.module('restangular', []);
4
-
5
- module.provider('Restangular', function() {
6
- // Configuration
7
- var Configurer = {};
8
- Configurer.init = function(object, config) {
9
- /**
10
- * Those are HTTP safe methods for which there is no need to pass any data with the request.
11
- */
12
-
13
- object.configuration = config;
14
-
15
- var safeMethods= ["get", "head", "options", "trace", "getlist"];
16
- config.isSafe = function(operation) {
17
- return _.contains(safeMethods, operation.toLowerCase());
18
- };
19
-
20
- var absolutePattern = /^https?:\/\//i;
21
- config.isAbsoluteUrl = function(string) {
22
- return string && absolutePattern.test(string);
23
- };
24
- /**
25
- * This is the BaseURL to be used with Restangular
26
- */
27
- config.baseUrl = _.isUndefined(config.baseUrl) ? "" : config.baseUrl;
28
- object.setBaseUrl = function(newBaseUrl) {
29
- config.baseUrl = /\/$/.test(newBaseUrl)
30
- ? newBaseUrl.substring(0, newBaseUrl.length-1)
31
- : newBaseUrl;
32
- return this;
33
- };
34
-
35
- /**
36
- * Sets the extra fields to keep from the parents
37
- */
38
- config.extraFields = config.extraFields || [];
39
- object.setExtraFields = function(newExtraFields) {
40
- config.extraFields = newExtraFields;
41
- return this;
42
- };
43
-
44
- /**
45
- * Some default $http parameter to be used in EVERY call
46
- **/
47
- config.defaultHttpFields = config.defaultHttpFields || {};
48
- object.setDefaultHttpFields = function(values) {
49
- config.defaultHttpFields = values;
50
- return this;
51
- };
52
-
53
- config.withHttpValues = function(httpLocalConfig, obj) {
54
- return _.defaults(obj, httpLocalConfig, config.defaultHttpFields);
55
- };
56
-
57
- config.encodeIds = _.isUndefined(config.encodeIds) ? true : config.encodeIds;
58
- object.setEncodeIds = function(encode) {
59
- config.encodeIds = encode;
60
- }
61
-
62
- config.defaultRequestParams = config.defaultRequestParams || {
63
- get: {},
64
- post: {},
65
- put: {},
66
- remove: {},
67
- common: {}
68
- };
69
-
70
- object.setDefaultRequestParams = function(param1, param2) {
71
- var methods = [],
72
- params = param2 || param1;
73
- if (!_.isUndefined(param2)) {
74
- if (_.isArray(param1)) {
75
- methods = param1;
76
- } else {
77
- methods.push(param1);
78
- }
79
- } else {
80
- methods.push('common');
81
- }
82
-
83
- _.each(methods, function (method) {
84
- config.defaultRequestParams[method] = params;
85
- });
86
- return this;
87
- }
88
-
89
- object.requestParams = config.defaultRequestParams;
90
-
91
-
92
- config.defaultHeaders = config.defaultHeaders || {};
93
- object.setDefaultHeaders = function(headers) {
94
- config.defaultHeaders = headers;
95
- object.defaultHeaders = config.defaultHeaders;
96
- return this;
97
- };
98
-
99
- object.defaultHeaders = config.defaultHeaders;
100
-
101
- /**
102
- * Method overriders will set which methods are sent via POST with an X-HTTP-Method-Override
103
- **/
104
- config.methodOverriders = config.methodOverriders || [];
105
- object.setMethodOverriders = function(values) {
106
- var overriders = _.extend([], values);
107
- if (config.isOverridenMethod('delete', overriders)) {
108
- overriders.push("remove");
109
- }
110
- config.methodOverriders = overriders;
111
- return this;
112
- };
113
-
114
- config.isOverridenMethod = function(method, values) {
115
- var search = values || config.methodOverriders;
116
- return !_.isUndefined(_.find(search, function(one) {
117
- return one.toLowerCase() === method.toLowerCase();
118
- }));
119
- };
120
-
121
- /**
122
- * Sets the URL creator type. For now, only Path is created. In the future we'll have queryParams
123
- **/
124
- config.urlCreator = config.urlCreator || "path";
125
- object.setUrlCreator = function(name) {
126
- if (!_.has(config.urlCreatorFactory, name)) {
127
- throw new Error("URL Path selected isn't valid");
128
- }
129
-
130
- config.urlCreator = name;
131
- return this;
132
- };
133
-
134
- /**
135
- * You can set the restangular fields here. The 3 required fields for Restangular are:
136
- *
137
- * id: Id of the element
138
- * route: name of the route of this element
139
- * parentResource: the reference to the parent resource
140
- *
141
- * All of this fields except for id, are handled (and created) by Restangular. By default,
142
- * the field values will be id, route and parentResource respectively
143
- */
144
- config.restangularFields = config.restangularFields || {
145
- id: "id",
146
- route: "route",
147
- parentResource: "parentResource",
148
- restangularCollection: "restangularCollection",
149
- cannonicalId: "__cannonicalId",
150
- etag: "restangularEtag",
151
- selfLink: "href",
152
- get: "get",
153
- getList: "getList",
154
- put: "put",
155
- post: "post",
156
- remove: "remove",
157
- head: "head",
158
- trace: "trace",
159
- options: "options",
160
- patch: "patch",
161
- getRestangularUrl: "getRestangularUrl",
162
- putElement: "putElement",
163
- addRestangularMethod: "addRestangularMethod",
164
- getParentList: "getParentList",
165
- clone: "clone",
166
- ids: "ids",
167
- httpConfig: '_$httpConfig'
168
- };
169
- object.setRestangularFields = function(resFields) {
170
- config.restangularFields =
171
- _.extend(config.restangularFields, resFields);
172
- return this;
173
- };
174
-
175
- config.setFieldToElem = function(field, elem, value) {
176
- var properties = field.split('.');
177
- var idValue = elem;
178
- _.each(_.initial(properties), function(prop) {
179
- idValue[prop] = {};
180
- idValue = idValue[prop];
181
- });
182
- idValue[_.last(properties)] = value;
183
- return this;
184
- };
185
-
186
- config.getFieldFromElem = function(field, elem) {
187
- var properties = field.split('.');
188
- var idValue = angular.copy(elem);
189
- _.each(properties, function(prop) {
190
- if (idValue) {
191
- idValue = idValue[prop];
192
- }
193
- });
194
- return idValue;
195
- };
196
-
197
- config.setIdToElem = function(elem, id) {
198
- config.setFieldToElem(config.restangularFields.id, elem, id);
199
- return this;
200
- };
201
-
202
- config.getIdFromElem = function(elem) {
203
- return config.getFieldFromElem(config.restangularFields.id, elem);
204
- };
205
-
206
- config.isValidId = function(elemId) {
207
- return "" !== elemId && !_.isUndefined(elemId) && !_.isNull(elemId)
208
- }
209
-
210
- config.setUrlToElem = function(elem, url) {
211
- config.setFieldToElem(config.restangularFields.selfLink, elem, url);
212
- return this;
213
- }
214
-
215
- config.getUrlFromElem = function(elem) {
216
- return config.getFieldFromElem(config.restangularFields.selfLink, elem);
217
- }
218
-
219
- config.useCannonicalId = _.isUndefined(config.useCannonicalId) ? false : config.useCannonicalId;
220
- object.setUseCannonicalId = function(value) {
221
- config.useCannonicalId = value;
222
- return this;
223
- }
224
-
225
- config.getCannonicalIdFromElem = function(elem) {
226
- var cannonicalId = elem[config.restangularFields.cannonicalId];
227
- var actualId = config.isValidId(cannonicalId) ?
228
- cannonicalId : config.getIdFromElem(elem);
229
- return actualId;
230
- };
231
-
232
- /**
233
- * Sets the Response parser. This is used in case your response isn't directly the data.
234
- * For example if you have a response like {meta: {'meta'}, data: {name: 'Gonto'}}
235
- * you can extract this data which is the one that needs wrapping
236
- *
237
- * The ResponseExtractor is a function that receives the response and the method executed.
238
- */
239
-
240
- config.responseExtractor = config.responseExtractor || function(data, operation,
241
- what, url, response, deferred) {
242
- return data;
243
- };
244
-
245
- object.setResponseExtractor = function(extractor) {
246
- config.responseExtractor = extractor;
247
- return this;
248
- };
249
-
250
- object.setResponseInterceptor = object.setResponseExtractor;
251
-
252
- /**
253
- * Response interceptor is called just before resolving promises.
254
- */
255
-
256
-
257
- /**
258
- * Request interceptor is called before sending an object to the server.
259
- */
260
- config.fullRequestInterceptor = config.fullRequestInterceptor || function(element, operation,
261
- path, url, headers, params, httpConfig) {
262
- return {
263
- element: element,
264
- headers: headers,
265
- params: params,
266
- httpConfig: httpConfig
267
- };
268
- };
269
-
270
- object.setRequestInterceptor = function(interceptor) {
271
- config.fullRequestInterceptor = function(elem, operation, path, url, headers, params, httpConfig) {
272
- return {
273
- headers: headers,
274
- params: params,
275
- element: interceptor(elem, operation, path, url),
276
- httpConfig: httpConfig
277
- }
278
- };
279
- return this;
280
- };
281
-
282
- object.setFullRequestInterceptor = function(interceptor) {
283
- config.fullRequestInterceptor = interceptor;
284
- return this;
285
- };
286
-
287
- config.errorInterceptor = config.errorInterceptor || function() {};
288
-
289
- object.setErrorInterceptor = function(interceptor) {
290
- config.errorInterceptor = interceptor;
291
- return this;
292
- };
293
-
294
- config.onBeforeElemRestangularized = config.onBeforeElemRestangularized || function(elem) {
295
- return elem;
296
- }
297
- object.setOnBeforeElemRestangularized = function(post) {
298
- config.onBeforeElemRestangularized = post;
299
- return this;
300
- };
301
-
302
- /**
303
- * This method is called after an element has been "Restangularized".
304
- *
305
- * It receives the element, a boolean indicating if it's an element or a collection
306
- * and the name of the model
307
- *
308
- */
309
- config.onElemRestangularized = config.onElemRestangularized || function(elem) {
310
- return elem;
311
- };
312
- object.setOnElemRestangularized = function(post) {
313
- config.onElemRestangularized = post;
314
- return this;
315
- };
316
-
317
- /**
318
- * Depracated. Don't use this!!
319
- */
320
- object.setListTypeIsArray = function(val) {
321
-
322
- };
323
-
324
- config.shouldSaveParent = config.shouldSaveParent || function() {
325
- return true;
326
- };
327
- object.setParentless = function(values) {
328
- if (_.isArray(values)) {
329
- config.shouldSaveParent = function(route) {
330
- return !_.contains(values, route);
331
- }
332
- } else if (_.isBoolean(values)) {
333
- config.shouldSaveParent = function() {
334
- return !values;
335
- }
336
- }
337
- return this;
338
- };
339
-
340
- /**
341
- * This lets you set a suffix to every request.
342
- *
343
- * For example, if your api requires that for JSon requests you do /users/123.json, you can set that
344
- * in here.
345
- *
346
- *
347
- * By default, the suffix is null
348
- */
349
- config.suffix = _.isUndefined(config.suffix) ? null : config.suffix;
350
- object.setRequestSuffix = function(newSuffix) {
351
- config.suffix = newSuffix;
352
- return this;
353
- };
354
-
355
- /**
356
- * Add element transformers for certain routes.
357
- */
358
- config.transformers = config.transformers || {};
359
- object.addElementTransformer = function(type, secondArg, thirdArg) {
360
- var isCollection = null;
361
- var transformer = null;
362
- if (arguments.length === 2) {
363
- transformer = secondArg;
364
- } else {
365
- transformer = thirdArg;
366
- isCollection = secondArg;
367
- }
368
-
369
- var typeTransformers = config.transformers[type];
370
- if (!typeTransformers) {
371
- typeTransformers = config.transformers[type] = [];
372
- }
373
-
374
- typeTransformers.push(function(coll, elem) {
375
- if (_.isNull(isCollection) || (coll == isCollection)) {
376
- return transformer(elem);
377
- }
378
- return elem;
379
- });
380
- };
381
-
382
- object.extendCollection = function(route, fn) {
383
- return object.addElementTransformer(route, true, fn);
384
- };
385
-
386
- object.extendModel = function(route, fn) {
387
- return object.addElementTransformer(route, false, fn);
388
- };
389
-
390
- config.transformElem = function(elem, isCollection, route, Restangular) {
391
- var typeTransformers = config.transformers[route];
392
- var changedElem = elem;
393
- if (typeTransformers) {
394
- _.each(typeTransformers, function(transformer) {
395
- changedElem = transformer(isCollection, changedElem);
396
- });
397
- }
398
- return config.onElemRestangularized(changedElem,
399
- isCollection, route, Restangular);
400
- };
401
-
402
- config.fullResponse = _.isUndefined(config.fullResponse) ? false : config.fullResponse;
403
- object.setFullResponse = function(full) {
404
- config.fullResponse = full;
405
- return this;
406
- };
407
-
408
-
409
-
410
- //Internal values and functions
411
- config.urlCreatorFactory = {};
412
-
413
- /**
414
- * Base URL Creator. Base prototype for everything related to it
415
- **/
416
-
417
- var BaseCreator = function() {
418
- };
419
-
420
- BaseCreator.prototype.setConfig = function(config) {
421
- this.config = config;
422
- return this;
423
- };
424
-
425
- BaseCreator.prototype.parentsArray = function(current) {
426
- var parents = [];
427
- while(current) {
428
- parents.push(current);
429
- current = current[this.config.restangularFields.parentResource];
430
- }
431
- return parents.reverse();
432
- };
433
-
434
- function RestangularResource(config, $http, url, configurer) {
435
- var resource = {};
436
- _.each(_.keys(configurer), function(key) {
437
- var value = configurer[key];
438
-
439
- // Add default parameters
440
- value.params = _.extend({}, value.params,
441
- config.defaultRequestParams[value.method.toLowerCase()]);
442
- // We don't want the ? if no params are there
443
- if (_.isEmpty(value.params)) {
444
- delete value.params;
445
- }
446
-
447
- if (config.isSafe(value.method)) {
448
-
449
- resource[key] = function() {
450
- return $http(_.extend(value, {
451
- url: url
452
- }));
453
- }
454
-
455
- } else {
456
-
457
- resource[key] = function(data) {
458
- return $http(_.extend(value, {
459
- url: url,
460
- data: data
461
- }));
462
- }
463
-
464
- }
465
- });
466
-
467
- return resource;
468
- }
469
-
470
- BaseCreator.prototype.resource = function(current, $http, localHttpConfig, callHeaders, callParams, what, etag, operation) {
471
-
472
- var params = _.defaults(callParams || {}, this.config.defaultRequestParams.common);
473
- var headers = _.defaults(callHeaders || {}, this.config.defaultHeaders);
474
-
475
- if (etag) {
476
- if (!config.isSafe(operation)) {
477
- headers['If-Match'] = etag;
478
- } else {
479
- headers['If-None-Match'] = etag;
480
- }
481
- }
482
-
483
- var url = this.base(current);
484
-
485
- if (what) {
486
- var add = '';
487
- if (!/\/$/.test(url)) {
488
- add += '/';
489
- }
490
- add += what;
491
- url += add;
492
- }
493
-
494
- if (this.config.suffix
495
- && url.indexOf(this.config.suffix, url.length - this.config.suffix.length) === -1) {
496
-
497
- url += this.config.suffix;
498
- }
499
-
500
- current[this.config.restangularFields.httpConfig] = undefined;
501
-
502
-
503
- return RestangularResource(this.config, $http, url, {
504
- getList: this.config.withHttpValues(localHttpConfig,
505
- {method: 'GET',
506
- params: params,
507
- headers: headers}),
508
-
509
- get: this.config.withHttpValues(localHttpConfig,
510
- {method: 'GET',
511
- params: params,
512
- headers: headers}),
513
-
514
- put: this.config.withHttpValues(localHttpConfig,
515
- {method: 'PUT',
516
- params: params,
517
- headers: headers}),
518
-
519
- post: this.config.withHttpValues(localHttpConfig,
520
- {method: 'POST',
521
- params: params,
522
- headers: headers}),
523
-
524
- remove: this.config.withHttpValues(localHttpConfig,
525
- {method: 'DELETE',
526
- params: params,
527
- headers: headers}),
528
-
529
- head: this.config.withHttpValues(localHttpConfig,
530
- {method: 'HEAD',
531
- params: params,
532
- headers: headers}),
533
-
534
- trace: this.config.withHttpValues(localHttpConfig,
535
- {method: 'TRACE',
536
- params: params,
537
- headers: headers}),
538
-
539
- options: this.config.withHttpValues(localHttpConfig,
540
- {method: 'OPTIONS',
541
- params: params,
542
- headers: headers}),
543
-
544
- patch: this.config.withHttpValues(localHttpConfig,
545
- {method: 'PATCH',
546
- params: params,
547
- headers: headers})
548
- });
549
- };
550
-
551
- /**
552
- * This is the Path URL creator. It uses Path to show Hierarchy in the Rest API.
553
- * This means that if you have an Account that then has a set of Buildings, a URL to a building
554
- * would be /accounts/123/buildings/456
555
- **/
556
- var Path = function() {
557
- };
558
-
559
- Path.prototype = new BaseCreator();
560
-
561
- Path.prototype.base = function(current) {
562
- var __this = this;
563
- return _.reduce(this.parentsArray(current), function(acum, elem) {
564
- var elemUrl;
565
- var elemSelfLink = __this.config.getUrlFromElem(elem);
566
- if (elemSelfLink) {
567
- if (__this.config.isAbsoluteUrl(elemSelfLink)) {
568
- return elemSelfLink;
569
- } else {
570
- elemUrl = elemSelfLink;
571
- }
572
- } else {
573
- elemUrl = elem[__this.config.restangularFields.route];
574
-
575
- if (elem[__this.config.restangularFields.restangularCollection]) {
576
- var ids = elem[__this.config.restangularFields.ids];
577
- if (ids) {
578
- elemUrl += "/" + ids.join(",");
579
- }
580
- } else {
581
- var elemId;
582
- if (__this.config.useCannonicalId) {
583
- elemId = __this.config.getCannonicalIdFromElem(elem);
584
- } else {
585
- elemId = __this.config.getIdFromElem(elem);
586
- }
587
-
588
- if (config.isValidId(elemId)) {
589
- elemUrl += "/" + (__this.config.encodeIds ? encodeURIComponent(elemId) : elemId);
590
- }
591
- }
592
- }
593
-
594
- return acum + "/" + elemUrl;
595
-
596
- }, this.config.baseUrl);
597
- };
598
-
599
-
600
-
601
- Path.prototype.fetchUrl = function(current, what) {
602
- var baseUrl = this.base(current);
603
- if (what) {
604
- baseUrl += "/" + what;
605
- }
606
- return baseUrl;
607
- };
608
-
609
-
610
-
611
- config.urlCreatorFactory.path = Path;
612
-
613
- }
614
-
615
- var globalConfiguration = {};
616
-
617
- Configurer.init(this, globalConfiguration);
618
-
619
-
620
-
621
-
622
- this.$get = ['$http', '$q', function($http, $q) {
623
-
624
- function createServiceForConfiguration(config) {
625
- var service = {};
626
-
627
- var urlHandler = new config.urlCreatorFactory[config.urlCreator]();
628
- urlHandler.setConfig(config);
629
-
630
- function restangularizeBase(parent, elem, route) {
631
- elem[config.restangularFields.route] = route;
632
- elem[config.restangularFields.getRestangularUrl] = _.bind(urlHandler.fetchUrl, urlHandler, elem);
633
- elem[config.restangularFields.addRestangularMethod] = _.bind(addRestangularMethodFunction, elem);
634
- elem[config.restangularFields.clone] = _.bind(copyRestangularizedElement, elem, elem);
635
- elem.withHttpConfig = _.bind(withHttpConfig, elem);
636
-
637
- // RequestLess connection
638
- elem.one = _.bind(one, elem, elem);
639
- elem.all = _.bind(all, elem, elem);
640
- elem.several = _.bind(several, elem, elem);
641
- elem.oneUrl = _.bind(oneUrl, elem, elem);
642
- elem.allUrl = _.bind(allUrl, elem, elem);
643
-
644
- if (parent && config.shouldSaveParent(route)) {
645
- var parentId = config.getIdFromElem(parent);
646
- var parentUrl = config.getUrlFromElem(parent);
647
-
648
- var restangularFieldsForParent = _.union(
649
- _.values( _.pick(config.restangularFields, ['route', 'parentResource']) ),
650
- config.extraFields
651
- );
652
- var parentResource = _.pick(parent, restangularFieldsForParent);
653
-
654
- if (config.isValidId(parentId)) {
655
- config.setIdToElem(parentResource, parentId);
656
- }
657
- if (config.isValidId(parentUrl)) {
658
- config.setUrlToElem(parentResource, parentUrl);
659
- }
660
-
661
- elem[config.restangularFields.parentResource] = parentResource;
662
- } else {
663
- elem[config.restangularFields.parentResource] = null;
664
- }
665
- return elem;
666
- }
667
-
668
-
669
-
670
- function one(parent, route, id) {
671
- var elem = {};
672
- config.setIdToElem(elem, id);
673
- return restangularizeElem(parent, elem , route);
674
- }
675
-
676
-
677
- function all(parent, route) {
678
- return restangularizeCollection(parent, [] , route, true);
679
- }
680
-
681
- function several(parent, route, ids) {
682
- var collection = [];
683
- collection[config.restangularFields.ids] =
684
- Array.prototype.splice.call(arguments, 2);
685
- return restangularizeCollection(parent, collection , route, true);
686
- }
687
-
688
- function oneUrl(parent, route, url) {
689
- var elem = {};
690
- config.setUrlToElem(elem, url);
691
- return restangularizeElem(parent, elem , route);
692
- }
693
-
694
-
695
- function allUrl(parent, route, url) {
696
- var elem = {};
697
- config.setUrlToElem(elem, url);
698
- return restangularizeCollection(parent, elem , route, true);
699
- }
700
- // Promises
701
- function restangularizePromise(promise, isCollection) {
702
- promise.call = _.bind(promiseCall, promise);
703
- promise.get = _.bind(promiseGet, promise);
704
- promise[config.restangularFields.restangularCollection] = isCollection;
705
- if (isCollection) {
706
- promise.push = _.bind(promiseCall, promise, "push");
707
- }
708
- return promise;
709
- }
710
-
711
- function promiseCall(method) {
712
- var deferred = $q.defer();
713
- var callArgs = arguments;
714
- this.then(function(val) {
715
- var params = Array.prototype.slice.call(callArgs, 1);
716
- var func = val[method];
717
- func.apply(val, params);
718
- deferred.resolve(val);
719
- });
720
- return restangularizePromise(deferred.promise, this[config.restangularFields.restangularCollection]);
721
- }
722
-
723
- function promiseGet(what) {
724
- var deferred = $q.defer();
725
- this.then(function(val) {
726
- deferred.resolve(val[what]);
727
- });
728
- return restangularizePromise(deferred.promise, this[config.restangularFields.restangularCollection]);
729
- }
730
-
731
- function resolvePromise(deferred, response, data) {
732
-
733
- // Trigger the full response interceptor.
734
- if (config.fullResponse) {
735
- return deferred.resolve(_.extend(response, {
736
- data: data
737
- }));
738
- } else {
739
- deferred.resolve(data);
740
- }
741
- }
742
-
743
-
744
- // Elements
745
-
746
- function stripRestangular(elem) {
747
- return _.omit(elem, _.values(_.omit(config.restangularFields, 'id')));
748
- }
749
-
750
- function addCustomOperation(elem) {
751
- elem.customOperation = _.bind(customFunction, elem);
752
- _.each(["put", "post", "get", "delete"], function(oper) {
753
- _.each(["do", "custom"], function(alias) {
754
- var callOperation = oper === 'delete' ? 'remove' : oper;
755
- var name = alias + oper.toUpperCase();
756
- var callFunction;
757
-
758
- if (callOperation !== 'put' && callOperation !== 'post') {
759
- callFunction = customFunction;
760
- } else {
761
- callFunction = function(operation, elem, path, params, headers) {
762
- return _.bind(customFunction, this)(operation, path, params, headers, elem);
763
- }
764
- }
765
- elem[name] = _.bind(callFunction, elem, callOperation);
766
- });
767
- });
768
- elem.customGETLIST = _.bind(fetchFunction, elem);
769
- elem.doGETLIST = elem.customGETLIST;
770
- }
771
-
772
- function copyRestangularizedElement(fromElement) {
773
- var copiedElement = angular.copy(fromElement);
774
- return restangularizeElem(copiedElement[config.restangularFields.parentResource],
775
- copiedElement, copiedElement[config.restangularFields.route]);
776
- }
777
-
778
- function restangularizeElem(parent, element, route, collection) {
779
- var elem = config.onBeforeElemRestangularized(element, false, route);
780
-
781
- var localElem = restangularizeBase(parent, elem, route);
782
-
783
- if (config.useCannonicalId) {
784
- localElem[config.restangularFields.cannonicalId] = config.getIdFromElem(localElem)
785
- }
786
-
787
- if (collection) {
788
- localElem[config.restangularFields.getParentList] = function() {
789
- return collection;
790
- }
791
- }
792
-
793
-
794
- localElem[config.restangularFields.restangularCollection] = false;
795
- localElem[config.restangularFields.get] = _.bind(getFunction, localElem);
796
- localElem[config.restangularFields.getList] = _.bind(fetchFunction, localElem);
797
- localElem[config.restangularFields.put] = _.bind(putFunction, localElem);
798
- localElem[config.restangularFields.post] = _.bind(postFunction, localElem);
799
- localElem[config.restangularFields.remove] = _.bind(deleteFunction, localElem);
800
- localElem[config.restangularFields.head] = _.bind(headFunction, localElem);
801
- localElem[config.restangularFields.trace] = _.bind(traceFunction, localElem);
802
- localElem[config.restangularFields.options] = _.bind(optionsFunction, localElem);
803
- localElem[config.restangularFields.patch] = _.bind(patchFunction, localElem);
804
-
805
- addCustomOperation(localElem);
806
- return config.transformElem(localElem, false, route, service);
807
- }
808
-
809
- function restangularizeCollection(parent, element, route) {
810
- var elem = config.onBeforeElemRestangularized(element, true, route);
811
-
812
- var localElem = restangularizeBase(parent, elem, route);
813
- localElem[config.restangularFields.restangularCollection] = true;
814
- localElem[config.restangularFields.post] = _.bind(postFunction, localElem, null);
815
- localElem[config.restangularFields.head] = _.bind(headFunction, localElem);
816
- localElem[config.restangularFields.trace] = _.bind(traceFunction, localElem);
817
- localElem[config.restangularFields.putElement] = _.bind(putElementFunction, localElem);
818
- localElem[config.restangularFields.options] = _.bind(optionsFunction, localElem);
819
- localElem[config.restangularFields.patch] = _.bind(patchFunction, localElem);
820
- localElem[config.restangularFields.get] = _.bind(getById, localElem);
821
- localElem[config.restangularFields.getList] = _.bind(fetchFunction, localElem, null);
822
-
823
- addCustomOperation(localElem);
824
- return config.transformElem(localElem, true, route, service);
825
- }
826
-
827
- function getById(id, reqParams, headers){
828
- return this.customGET(id.toString(), reqParams, headers);
829
- }
830
-
831
- function putElementFunction(idx, params, headers) {
832
- var __this = this;
833
- var elemToPut = this[idx];
834
- var deferred = $q.defer();
835
- elemToPut.put(params, headers).then(function(serverElem) {
836
- var newArray = copyRestangularizedElement(__this);
837
- newArray[idx] = serverElem;
838
- deferred.resolve(newArray);
839
- }, function(response) {
840
- deferred.reject(response);
841
- });
842
-
843
- return restangularizePromise(deferred.promise, true)
844
- }
845
-
846
- function parseResponse(resData, operation, route, fetchUrl, response, deferred) {
847
- var data = config.responseExtractor(resData, operation, route, fetchUrl, response, deferred);
848
- var etag = response.headers("ETag");
849
- if (data && etag) {
850
- data[config.restangularFields.etag] = etag;
851
- }
852
- return data;
853
- }
854
-
855
-
856
- function fetchFunction(what, reqParams, headers) {
857
- var __this = this;
858
- var deferred = $q.defer();
859
- var operation = 'getList';
860
- var url = urlHandler.fetchUrl(this, what);
861
- var whatFetched = what || __this[config.restangularFields.route];
862
-
863
-
864
- var request = config.fullRequestInterceptor(null, operation,
865
- whatFetched, url, headers || {}, reqParams || {}, this[config.restangularFields.httpConfig] || {});
866
-
867
- urlHandler.resource(this, $http, request.httpConfig, request.headers, request.params, what,
868
- this[config.restangularFields.etag], operation).getList().then(function(response) {
869
- var resData = response.data;
870
- var data = parseResponse(resData, operation, whatFetched, url, response, deferred);
871
- var processedData = _.map(data, function(elem) {
872
- if (!__this[config.restangularFields.restangularCollection]) {
873
- return restangularizeElem(__this, elem, what, data);
874
- } else {
875
- return restangularizeElem(__this[config.restangularFields.parentResource],
876
- elem, __this[config.restangularFields.route], data);
877
- }
878
-
879
- });
880
-
881
- processedData = _.extend(data, processedData);
882
- if (!__this[config.restangularFields.restangularCollection]) {
883
- resolvePromise(deferred, response, restangularizeCollection(__this, processedData, what));
884
- } else {
885
- resolvePromise(deferred, response, restangularizeCollection(__this[config.restangularFields.parentResource], processedData, __this[config.restangularFields.route]));
886
- }
887
- }, function error(response) {
888
- if ( config.errorInterceptor(response) !== false ) {
889
- deferred.reject(response);
890
- }
891
- });
892
-
893
- return restangularizePromise(deferred.promise, true);
894
- }
895
-
896
- function withHttpConfig(httpConfig) {
897
- this[config.restangularFields.httpConfig] = httpConfig;
898
- return this;
899
- }
900
-
901
- function elemFunction(operation, what, params, obj, headers) {
902
- var __this = this;
903
- var deferred = $q.defer();
904
- var resParams = params || {};
905
- var route = what || this[config.restangularFields.route];
906
- var fetchUrl = urlHandler.fetchUrl(this, what);
907
-
908
- var callObj = obj || this;
909
- var etag = callObj[config.restangularFields.etag];
910
- if (_.isObject(callObj)) {
911
- callObj = stripRestangular(callObj);
912
- }
913
- var request = config.fullRequestInterceptor(callObj, operation, route, fetchUrl,
914
- headers || {}, resParams || {}, this[config.restangularFields.httpConfig] || {});
915
-
916
- var okCallback = function(response) {
917
- var resData = response.data;
918
- var elem = parseResponse(resData, operation, route, fetchUrl, response, deferred);
919
- if (elem) {
920
-
921
- if (operation === "post" && !__this[config.restangularFields.restangularCollection]) {
922
- resolvePromise(deferred, response, restangularizeElem(__this, elem, what));
923
- } else {
924
- resolvePromise(deferred, response, restangularizeElem(__this[config.restangularFields.parentResource], elem, __this[config.restangularFields.route]));
925
- }
926
-
927
- } else {
928
- resolvePromise(deferred, response, undefined);
929
- }
930
- };
931
-
932
- var errorCallback = function(response) {
933
- if ( config.errorInterceptor(response) !== false ) {
934
- deferred.reject(response);
935
- }
936
- };
937
- // Overring HTTP Method
938
- var callOperation = operation;
939
- var callHeaders = _.extend({}, request.headers);
940
- var isOverrideOperation = config.isOverridenMethod(operation);
941
- if (isOverrideOperation) {
942
- callOperation = 'post';
943
- callHeaders = _.extend(callHeaders, {'X-HTTP-Method-Override': operation === 'remove' ? 'DELETE' : operation});
944
- }
945
-
946
- if (config.isSafe(operation)) {
947
- if (isOverrideOperation) {
948
- urlHandler.resource(this, $http, request.httpConfig, callHeaders, request.params,
949
- what, etag, callOperation)[callOperation]({}).then(okCallback, errorCallback);
950
- } else {
951
- urlHandler.resource(this, $http, request.httpConfig, callHeaders, request.params,
952
- what, etag, callOperation)[callOperation]().then(okCallback, errorCallback);
953
- }
954
- } else {
955
- urlHandler.resource(this, $http, request.httpConfig, callHeaders, request.params,
956
- what, etag, callOperation)[callOperation](request.element).then(okCallback, errorCallback);
957
- }
958
-
959
- return restangularizePromise(deferred.promise);
960
- }
961
-
962
- function getFunction(params, headers) {
963
- return _.bind(elemFunction, this)("get", undefined, params, undefined, headers);
964
- }
965
-
966
- function deleteFunction(params, headers) {
967
- return _.bind(elemFunction, this)("remove", undefined, params, undefined, headers);
968
- }
969
-
970
- function putFunction(params, headers) {
971
- return _.bind(elemFunction, this)("put", undefined, params, undefined, headers);
972
- }
973
-
974
- function postFunction(what, elem, params, headers) {
975
- return _.bind(elemFunction, this)("post", what, params, elem, headers);
976
- }
977
-
978
- function headFunction(params, headers) {
979
- return _.bind(elemFunction, this)("head", undefined, params, undefined, headers);
980
- }
981
-
982
- function traceFunction(params, headers) {
983
- return _.bind(elemFunction, this)("trace", undefined, params, undefined, headers);
984
- }
985
-
986
- function optionsFunction(params, headers) {
987
- return _.bind(elemFunction, this)("options", undefined, params, undefined, headers);
988
- }
989
-
990
- function patchFunction(elem, params, headers) {
991
- return _.bind(elemFunction, this)("patch", undefined, params, elem, headers);
992
- }
993
-
994
- function customFunction(operation, path, params, headers, elem) {
995
- return _.bind(elemFunction, this)(operation, path, params, elem, headers);
996
- }
997
-
998
- function addRestangularMethodFunction(name, operation, path, defaultParams, defaultHeaders, defaultElem) {
999
- var bindedFunction;
1000
- if (operation === 'getList') {
1001
- bindedFunction = _.bind(fetchFunction, this, path);
1002
- } else {
1003
- bindedFunction = _.bind(customFunction, this, operation, path);
1004
- }
1005
-
1006
- var createdFunction = function(params, headers, elem) {
1007
- var callParams = _.defaults({
1008
- params: params,
1009
- headers: headers,
1010
- elem: elem
1011
- }, {
1012
- params: defaultParams,
1013
- headers: defaultHeaders,
1014
- elem: defaultElem
1015
- });
1016
- return bindedFunction(callParams.params, callParams.headers, callParams.elem);
1017
- };
1018
-
1019
- if (config.isSafe(operation)) {
1020
- this[name] = createdFunction;
1021
- } else {
1022
- this[name] = function(elem, params, headers) {
1023
- return createdFunction(params, headers, elem);
1024
- }
1025
- }
1026
-
1027
- }
1028
-
1029
- function withConfigurationFunction(configurer) {
1030
- var newConfig = angular.copy(globalConfiguration);
1031
- Configurer.init(newConfig, newConfig);
1032
- configurer(newConfig);
1033
- return createServiceForConfiguration(newConfig);
1034
- }
1035
-
1036
-
1037
- Configurer.init(service, config);
1038
-
1039
- service.copy = _.bind(copyRestangularizedElement, service);
1040
-
1041
- service.withConfig = _.bind(withConfigurationFunction, service);
1042
-
1043
- service.one = _.bind(one, service, null);
1044
-
1045
- service.all = _.bind(all, service, null);
1046
-
1047
- service.several = _.bind(several, service, null);
1048
-
1049
- service.oneUrl = _.bind(oneUrl, service, null);
1050
-
1051
- service.allUrl = _.bind(allUrl, service, null);
1052
-
1053
- service.restangularizeElement = _.bind(restangularizeElem, service);
1054
-
1055
- service.restangularizeCollection = _.bind(restangularizeCollection, service);
1056
-
1057
- return service;
1058
- }
1059
-
1060
- return createServiceForConfiguration(globalConfiguration);
1061
-
1062
- }];
1063
- }
1064
- );
1065
-
1066
- })();