faalis 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (286) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +339 -0
  3. data/README.md +45 -0
  4. data/Rakefile +42 -0
  5. data/app/assets/fonts/DroidNaskh-Bold.ttf +0 -0
  6. data/app/assets/fonts/DroidNaskh-Regular.ttf +0 -0
  7. data/app/assets/fonts/OpenSans-Bold.ttf +0 -0
  8. data/app/assets/fonts/OpenSans-BoldItalic.ttf +0 -0
  9. data/app/assets/fonts/OpenSans-ExtraBold.ttf +0 -0
  10. data/app/assets/fonts/OpenSans-ExtraBoldItalic.ttf +0 -0
  11. data/app/assets/fonts/OpenSans-Italic.ttf +0 -0
  12. data/app/assets/fonts/OpenSans-Light.ttf +0 -0
  13. data/app/assets/fonts/OpenSans-LightItalic.ttf +0 -0
  14. data/app/assets/fonts/OpenSans-Regular.ttf +0 -0
  15. data/app/assets/fonts/OpenSans-Semibold.ttf +0 -0
  16. data/app/assets/fonts/OpenSans-SemiboldItalic.ttf +0 -0
  17. data/app/assets/images/faalis/select2-spinner.gif +0 -0
  18. data/app/assets/images/faalis/select2.png +0 -0
  19. data/app/assets/images/faalis/select2x2.png +0 -0
  20. data/app/assets/javascripts/faalis/application.js +20 -0
  21. data/app/assets/javascripts/faalis/dashboard/angular.js +9 -0
  22. data/app/assets/javascripts/faalis/dashboard/app.js +75 -0
  23. data/app/assets/javascripts/faalis/dashboard/application.js.erb +21 -0
  24. data/app/assets/javascripts/faalis/dashboard/functions.js.erb +91 -0
  25. data/app/assets/javascripts/faalis/dashboard/init.js +38 -0
  26. data/app/assets/javascripts/faalis/dashboard/lib/angular-animate.js +1226 -0
  27. data/app/assets/javascripts/faalis/dashboard/lib/angular-gettext.js +202 -0
  28. data/app/assets/javascripts/faalis/dashboard/lib/angular-resource.js +578 -0
  29. data/app/assets/javascripts/faalis/dashboard/lib/angular-route.js +880 -0
  30. data/app/assets/javascripts/faalis/dashboard/lib/angular.js +20031 -0
  31. data/app/assets/javascripts/faalis/dashboard/lib/lodash.underscore.js +4893 -0
  32. data/app/assets/javascripts/faalis/dashboard/lib/ng-grid.js +3260 -0
  33. data/app/assets/javascripts/faalis/dashboard/lib/ng-quick-date.js +297 -0
  34. data/app/assets/javascripts/faalis/dashboard/lib/restangular.js +1066 -0
  35. data/app/assets/javascripts/faalis/dashboard/lib/select2.js +3255 -0
  36. data/app/assets/javascripts/faalis/dashboard/lib/ui.select2.js +217 -0
  37. data/app/assets/javascripts/faalis/dashboard/locale/translations.js +5 -0
  38. data/app/assets/javascripts/faalis/dashboard/modules/anim.js +32 -0
  39. data/app/assets/javascripts/faalis/dashboard/modules/api.js +32 -0
  40. data/app/assets/javascripts/faalis/dashboard/modules/auth/auth.js +34 -0
  41. data/app/assets/javascripts/faalis/dashboard/modules/auth/group.js +174 -0
  42. data/app/assets/javascripts/faalis/dashboard/modules/auth/profile.js +59 -0
  43. data/app/assets/javascripts/faalis/dashboard/modules/auth/user.js +123 -0
  44. data/app/assets/javascripts/faalis/dashboard/modules/errors.js +47 -0
  45. data/app/assets/javascripts/faalis/dashboard/modules/filter.js +44 -0
  46. data/app/assets/javascripts/faalis/dashboard/modules/list-view.js +310 -0
  47. data/app/assets/javascripts/faalis/dashboard/modules/logs.js +41 -0
  48. data/app/assets/javascripts/faalis/dashboard/modules/modules.js +50 -0
  49. data/app/assets/javascripts/faalis/dashboard/modules/nav.js.erb +97 -0
  50. data/app/assets/javascripts/faalis/dashboard/templates/application.handlebars.erb +42 -0
  51. data/app/assets/javascripts/faalis/dashboard/templates/auth/groups/details.handlebars.erb +15 -0
  52. data/app/assets/javascripts/faalis/dashboard/templates/auth/groups/index.handlebars.erb +7 -0
  53. data/app/assets/javascripts/faalis/dashboard/templates/auth/groups/new.handlebars.erb +39 -0
  54. data/app/assets/javascripts/faalis/dashboard/templates/auth/index.handlebars.erb +31 -0
  55. data/app/assets/javascripts/faalis/dashboard/templates/auth/users/details.handlebars.erb +15 -0
  56. data/app/assets/javascripts/faalis/dashboard/templates/auth/users/index.handlebars.erb +11 -0
  57. data/app/assets/javascripts/faalis/dashboard/templates/auth/users/new.handlebars.erb +33 -0
  58. data/app/assets/javascripts/faalis/dashboard/templates/components/list-view.handlebars.erb +59 -0
  59. data/app/assets/javascripts/faalis/dashboard/templates/components/model-form.handlebars.erb +3 -0
  60. data/app/assets/javascripts/faalis/dashboard/templates/modules.handlebars.erb +15 -0
  61. data/app/assets/javascripts/faalis/dashboard/templates/navigation.handlebars.erb +43 -0
  62. data/app/assets/javascripts/faalis/dashboard/templates/widgets.handlebars +23 -0
  63. data/app/assets/javascripts/faalis/dashboard/variables.js.erb +17 -0
  64. data/app/assets/javascripts/faalis/groups.js +2 -0
  65. data/app/assets/javascripts/faalis/home.js +2 -0
  66. data/app/assets/javascripts/faalis/i18n.js +13 -0
  67. data/app/assets/javascripts/faalis/locale/en.json +27 -0
  68. data/app/assets/javascripts/faalis/locale/fa.json +27 -0
  69. data/app/assets/javascripts/faalis/users.js +2 -0
  70. data/app/assets/stylesheets/faalis/base.css.scss +264 -0
  71. data/app/assets/stylesheets/faalis/dashboard/dashboard.css.scss +226 -0
  72. data/app/assets/stylesheets/faalis/dashboard/list_view.css.scss +169 -0
  73. data/app/assets/stylesheets/faalis/dashboard/ltr/application.css +26 -0
  74. data/app/assets/stylesheets/faalis/dashboard/ltr/base.css.scss.erb +28 -0
  75. data/app/assets/stylesheets/faalis/dashboard/ltr/buttons.css.scss.erb +48 -0
  76. data/app/assets/stylesheets/faalis/dashboard/ltr/direction.css.scss +38 -0
  77. data/app/assets/stylesheets/faalis/dashboard/ltr/foundation_and_overrides.css.scss +1014 -0
  78. data/app/assets/stylesheets/faalis/dashboard/ng-grid.css.scss +442 -0
  79. data/app/assets/stylesheets/faalis/dashboard/ng-quick-date-default-theme.css.scss +20 -0
  80. data/app/assets/stylesheets/faalis/dashboard/ng-quick-date.css.scss +19 -0
  81. data/app/assets/stylesheets/faalis/dashboard/rtl/application.css +26 -0
  82. data/app/assets/stylesheets/faalis/dashboard/rtl/base.css.scss.erb +31 -0
  83. data/app/assets/stylesheets/faalis/dashboard/rtl/base.css_flymake.scss +25 -0
  84. data/app/assets/stylesheets/faalis/dashboard/rtl/buttons.css.scss.erb +45 -0
  85. data/app/assets/stylesheets/faalis/dashboard/rtl/direction.css.scss +37 -0
  86. data/app/assets/stylesheets/faalis/dashboard/rtl/foundation_and_overrides.css.scss +1014 -0
  87. data/app/assets/stylesheets/faalis/dashboard/select2.css.scss.erb +618 -0
  88. data/app/assets/stylesheets/faalis/dashboard/sidebar.css.scss +93 -0
  89. data/app/assets/stylesheets/faalis/devise.css.scss +34 -0
  90. data/app/assets/stylesheets/faalis/groups.css +4 -0
  91. data/app/assets/stylesheets/faalis/home.css.scss +14 -0
  92. data/app/assets/stylesheets/faalis/ltr/application.css +20 -0
  93. data/app/assets/stylesheets/faalis/ltr/buttons.css.scss.erb +48 -0
  94. data/app/assets/stylesheets/faalis/ltr/foundation_and_overrides.scss.erb +1012 -0
  95. data/app/assets/stylesheets/faalis/mixins.css.scss +15 -0
  96. data/app/assets/stylesheets/faalis/rtl/application.css +20 -0
  97. data/app/assets/stylesheets/faalis/rtl/buttons.css.scss.erb +48 -0
  98. data/app/assets/stylesheets/faalis/rtl/foundation_and_overrides.scss.erb +1012 -0
  99. data/app/assets/stylesheets/faalis/users.css +4 -0
  100. data/app/assets/stylesheets/faalis/variables.css.scss +102 -0
  101. data/app/controllers/faalis/api/v1/groups_controller.rb +75 -0
  102. data/app/controllers/faalis/api/v1/logs_controller.rb +12 -0
  103. data/app/controllers/faalis/api/v1/permissions_controller.rb +17 -0
  104. data/app/controllers/faalis/api/v1/profiles_controller.rb +42 -0
  105. data/app/controllers/faalis/api/v1/users_controller.rb +75 -0
  106. data/app/controllers/faalis/api_controller.rb +51 -0
  107. data/app/controllers/faalis/application_controller.rb +34 -0
  108. data/app/controllers/faalis/dashboard_controller.rb +44 -0
  109. data/app/controllers/faalis/home_controller.rb +19 -0
  110. data/app/controllers/faalis/omniauth/callbacks_controller.rb +43 -0
  111. data/app/helpers/faalis/application_helper.rb +4 -0
  112. data/app/helpers/faalis/dashboard_helper.rb +5 -0
  113. data/app/helpers/faalis/groups_helper.rb +4 -0
  114. data/app/helpers/faalis/home_helper.rb +4 -0
  115. data/app/helpers/faalis/users_helper.rb +4 -0
  116. data/app/models/ability.rb +42 -0
  117. data/app/models/faalis/group.rb +27 -0
  118. data/app/models/faalis/permission.rb +15 -0
  119. data/app/models/faalis/user.rb +81 -0
  120. data/app/views/angularjs_templates/#index.html# +8 -0
  121. data/app/views/angularjs_templates/auth/groups/details.html +21 -0
  122. data/app/views/angularjs_templates/auth/groups/index.html +5 -0
  123. data/app/views/angularjs_templates/auth/groups/new.html +41 -0
  124. data/app/views/angularjs_templates/auth/index.html +30 -0
  125. data/app/views/angularjs_templates/auth/profile/edit.html +54 -0
  126. data/app/views/angularjs_templates/auth/users/details.html +28 -0
  127. data/app/views/angularjs_templates/auth/users/index.html +6 -0
  128. data/app/views/angularjs_templates/auth/users/new.html +56 -0
  129. data/app/views/angularjs_templates/filter/index.html +15 -0
  130. data/app/views/angularjs_templates/index.html +8 -0
  131. data/app/views/angularjs_templates/list-view/index.html +81 -0
  132. data/app/views/angularjs_templates/locale/fa.po +25 -0
  133. data/app/views/angularjs_templates/locale/templates.pot +24 -0
  134. data/app/views/angularjs_templates/logs/index.html +6 -0
  135. data/app/views/angularjs_templates/modules.html +17 -0
  136. data/app/views/angularjs_templates/nav.html.erb +38 -0
  137. data/app/views/devise/confirmations/new.html.erb +34 -0
  138. data/app/views/devise/mailer/confirmation_instructions.html.erb +5 -0
  139. data/app/views/devise/mailer/reset_password_instructions.html.erb +8 -0
  140. data/app/views/devise/mailer/unlock_instructions.html.erb +7 -0
  141. data/app/views/devise/passwords/edit.html.erb +44 -0
  142. data/app/views/devise/passwords/new.html.erb +32 -0
  143. data/app/views/devise/registrations/edit.html.erb +29 -0
  144. data/app/views/devise/registrations/new.html.erb +91 -0
  145. data/app/views/devise/sessions/new.html.erb +98 -0
  146. data/app/views/devise/shared/_links.erb +25 -0
  147. data/app/views/devise/unlocks/new.html.erb +30 -0
  148. data/app/views/faalis/api/v1/groups/create.json.jbuilder +4 -0
  149. data/app/views/faalis/api/v1/groups/destroy.html.erb +2 -0
  150. data/app/views/faalis/api/v1/groups/destroy.json.jbuilder +1 -0
  151. data/app/views/faalis/api/v1/groups/edit.html.erb +2 -0
  152. data/app/views/faalis/api/v1/groups/index.html.erb +2 -0
  153. data/app/views/faalis/api/v1/groups/index.json.jbuilder +6 -0
  154. data/app/views/faalis/api/v1/groups/new.html.erb +2 -0
  155. data/app/views/faalis/api/v1/groups/show.html.erb +2 -0
  156. data/app/views/faalis/api/v1/groups/show.json.jbuilder +5 -0
  157. data/app/views/faalis/api/v1/groups/update.json.jbuilder +4 -0
  158. data/app/views/faalis/api/v1/logs/index.json.jbuilder +1 -0
  159. data/app/views/faalis/api/v1/permissions/index.json.jbuilder +1 -0
  160. data/app/views/faalis/api/v1/users/create.html.erb +2 -0
  161. data/app/views/faalis/api/v1/users/create.json.jbuilder +1 -0
  162. data/app/views/faalis/api/v1/users/destroy.json.jbuilder +1 -0
  163. data/app/views/faalis/api/v1/users/distroy.html.erb +2 -0
  164. data/app/views/faalis/api/v1/users/edit.html.erb +2 -0
  165. data/app/views/faalis/api/v1/users/index.html.erb +2 -0
  166. data/app/views/faalis/api/v1/users/index.json.jbuilder +4 -0
  167. data/app/views/faalis/api/v1/users/show.html.erb +2 -0
  168. data/app/views/faalis/api/v1/users/show.json.jbuilder +2 -0
  169. data/app/views/faalis/api/v1/users/update.json.jbuilder +1 -0
  170. data/app/views/faalis/dashboard/index.html.erb +37 -0
  171. data/app/views/faalis/dashboard/login_required_page.html.erb +5 -0
  172. data/app/views/faalis/home/index.html.erb +119 -0
  173. data/app/views/layouts/faalis/application.html.erb +90 -0
  174. data/app/views/layouts/faalis/dashboard.html.erb +21 -0
  175. data/config/initializers/devise.rb +28 -0
  176. data/config/locales/devise.en.yml +59 -0
  177. data/config/locales/devise.fa.yml +56 -0
  178. data/config/locales/fa/LC_MESSAGES/faalis.mo +0 -0
  179. data/config/locales/fa/faalis.po +181 -0
  180. data/config/locales/fa/messages.mo +0 -0
  181. data/config/locales/faalis.pot +181 -0
  182. data/config/routes.rb +36 -0
  183. data/db/migrate/20131013091000_devise_create_red_base_users.rb +64 -0
  184. data/db/migrate/20131020124701_create_red_base_groups.rb +9 -0
  185. data/db/migrate/20131021170923_create_red_base_permissions.rb +10 -0
  186. data/db/migrate/20131123120422_add_permissions_groups_table.rb +8 -0
  187. data/db/seeds.rb +15 -0
  188. data/lib/faalis.rb +30 -0
  189. data/lib/faalis/active_record.rb +64 -0
  190. data/lib/faalis/api.rb +61 -0
  191. data/lib/faalis/api/groups_api.rb +41 -0
  192. data/lib/faalis/api/permissions_api.rb +24 -0
  193. data/lib/faalis/api/root.rb +15 -0
  194. data/lib/faalis/api/users_api.rb +20 -0
  195. data/lib/faalis/cucumber.rb +25 -0
  196. data/lib/faalis/cucumber/auth.rb +45 -0
  197. data/lib/faalis/cucumber/exceptions.rb +40 -0
  198. data/lib/faalis/cucumber/interaction.rb +43 -0
  199. data/lib/faalis/cucumber/query.rb +28 -0
  200. data/lib/faalis/cucumber/urls.rb +76 -0
  201. data/lib/faalis/dashboard.rb +60 -0
  202. data/lib/faalis/dashboard/controller.rb +42 -0
  203. data/lib/faalis/dashboard/module.rb +45 -0
  204. data/lib/faalis/engine.rb +128 -0
  205. data/lib/faalis/exceptions.rb +26 -0
  206. data/lib/faalis/i18n.rb +35 -0
  207. data/lib/faalis/initialize.rb +7 -0
  208. data/lib/faalis/omniauth.rb +24 -0
  209. data/lib/faalis/omniauth/callbacks.rb +58 -0
  210. data/lib/faalis/plugins.rb +44 -0
  211. data/lib/faalis/version.rb +22 -0
  212. data/lib/faalis_plugin.rb +476 -0
  213. data/lib/generators/faalis/USAGE +8 -0
  214. data/lib/generators/faalis/angularjs_resource_generator.rb +74 -0
  215. data/lib/generators/faalis/install_all_generator.rb +38 -0
  216. data/lib/generators/faalis/install_generator.rb +42 -0
  217. data/lib/generators/faalis/install_specs_generator.rb +48 -0
  218. data/lib/generators/faalis/js_scaffold_generator.rb +273 -0
  219. data/lib/generators/faalis/templates/README +41 -0
  220. data/lib/generators/faalis/templates/SPECS +13 -0
  221. data/lib/generators/faalis/templates/angularjs/details.html.erb +20 -0
  222. data/lib/generators/faalis/templates/angularjs/index.html.erb +62 -0
  223. data/lib/generators/faalis/templates/angularjs/module.js.erb +309 -0
  224. data/lib/generators/faalis/templates/angularjs/new.html.erb +105 -0
  225. data/lib/generators/faalis/templates/api/controller.rb.erb +56 -0
  226. data/lib/generators/faalis/templates/devise.rb +251 -0
  227. data/lib/generators/faalis/templates/faalis.rb +14 -0
  228. data/lib/generators/faalis/templates/fast_gettext.rb +4 -0
  229. data/lib/generators/faalis/templates/features/api.feature +92 -0
  230. data/lib/generators/faalis/templates/features/api.step.rb +7 -0
  231. data/lib/generators/faalis/templates/features/step_definitions/email_steps.rb +206 -0
  232. data/lib/generators/faalis/templates/features/support/email_spec.rb +1 -0
  233. data/lib/generators/faalis/templates/features/support/env.rb +79 -0
  234. data/lib/generators/faalis/templates/formtastic.rb +76 -0
  235. data/lib/generators/faalis/templates/js_scaffold.README +25 -0
  236. data/lib/generators/faalis/templates/seeds.rb +1 -0
  237. data/lib/generators/faalis/templates/spec/factories/groups.rb +5 -0
  238. data/lib/generators/faalis/templates/spec/factories/users.rb +10 -0
  239. data/lib/generators/faalis/templates/spec/spec_helper.rb +69 -0
  240. data/lib/generators/faalis/templates/spec/support/devise.rb +3 -0
  241. data/lib/generators/faalis/templates/views/create.json.jbuilder.erb +2 -0
  242. data/lib/generators/faalis/templates/views/destroy.json.jbuilder.erb +1 -0
  243. data/lib/generators/faalis/templates/views/index.json.jbuilder.erb +10 -0
  244. data/lib/generators/faalis/templates/views/show.json.jbuilder.erb +7 -0
  245. data/lib/generators/faalis/templates/views/update.json.jbuilder.erb +6 -0
  246. data/lib/generators/faalis/views_generator.rb +41 -0
  247. data/lib/tasks/faalis_tasks.rake +23 -0
  248. data/lib/tasks/grunt/Gruntfile.js +25 -0
  249. data/spec/dummy/README.rdoc +28 -0
  250. data/spec/dummy/Rakefile +6 -0
  251. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  252. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  253. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  254. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  255. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  256. data/spec/dummy/bin/bundle +3 -0
  257. data/spec/dummy/bin/rails +4 -0
  258. data/spec/dummy/bin/rake +4 -0
  259. data/spec/dummy/config.ru +4 -0
  260. data/spec/dummy/config/application.rb +23 -0
  261. data/spec/dummy/config/boot.rb +5 -0
  262. data/spec/dummy/config/database.yml +25 -0
  263. data/spec/dummy/config/environment.rb +5 -0
  264. data/spec/dummy/config/environments/development.rb +29 -0
  265. data/spec/dummy/config/environments/production.rb +80 -0
  266. data/spec/dummy/config/environments/test.rb +36 -0
  267. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  268. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  269. data/spec/dummy/config/initializers/inflections.rb +16 -0
  270. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  271. data/spec/dummy/config/initializers/secret_token.rb +12 -0
  272. data/spec/dummy/config/initializers/session_store.rb +3 -0
  273. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  274. data/spec/dummy/config/locales/en.yml +23 -0
  275. data/spec/dummy/config/routes.rb +4 -0
  276. data/spec/dummy/db/test.sqlite3 +0 -0
  277. data/spec/dummy/log/development.log +0 -0
  278. data/spec/dummy/log/test.log +15 -0
  279. data/spec/dummy/public/404.html +58 -0
  280. data/spec/dummy/public/422.html +58 -0
  281. data/spec/dummy/public/500.html +57 -0
  282. data/spec/dummy/public/favicon.ico +0 -0
  283. data/spec/dummy/tmp/ember-rails/ember-data.js +10204 -0
  284. data/spec/dummy/tmp/ember-rails/ember.js +36991 -0
  285. data/spec/spec_helper.rb +52 -0
  286. metadata +678 -0
@@ -0,0 +1,202 @@
1
+ if (typeof jQuery === 'undefined') {
2
+ throw new Error('Angular-gettext depends on jQuery, be sure to include it!');
3
+ }
4
+ angular.module('gettext', []);
5
+ angular.module('gettext').factory('gettext', function () {
6
+ return function (str) {
7
+ return str;
8
+ };
9
+ });
10
+ angular.module('gettext').factory('gettextCatalog', [
11
+ 'gettextPlurals',
12
+ function (gettextPlurals) {
13
+ var catalog;
14
+ var prefixDebug = function (string) {
15
+ if (catalog.debug && catalog.currentLanguage !== 'en') {
16
+ return '[MISSING]: ' + string;
17
+ } else {
18
+ return string;
19
+ }
20
+ };
21
+ catalog = {
22
+ debug: false,
23
+ strings: {},
24
+ currentLanguage: 'en',
25
+ setStrings: function (language, strings) {
26
+ var key, val, _results;
27
+ if (!this.strings[language]) {
28
+ this.strings[language] = {};
29
+ }
30
+ for (key in strings) {
31
+ val = strings[key];
32
+ if (typeof val === 'string') {
33
+ this.strings[language][key] = [val];
34
+ } else {
35
+ this.strings[language][key] = val;
36
+ }
37
+ }
38
+ },
39
+ getStringForm: function (string, n) {
40
+ var stringTable = this.strings[this.currentLanguage] || {};
41
+ var plurals = stringTable[string] || [];
42
+ return plurals[n];
43
+ },
44
+ getString: function (string) {
45
+ return this.getStringForm(string, 0) || prefixDebug(string);
46
+ },
47
+ getPlural: function (n, string, stringPlural) {
48
+ var form = gettextPlurals(this.currentLanguage, n);
49
+ return this.getStringForm(string, form) || prefixDebug(n === 1 ? string : stringPlural);
50
+ }
51
+ };
52
+ return catalog;
53
+ }
54
+ ]);
55
+ angular.module('gettext').directive('translate', [
56
+ 'gettextCatalog',
57
+ '$interpolate',
58
+ '$parse',
59
+ function (gettextCatalog, $interpolate, $parse) {
60
+ return {
61
+ transclude: 'element',
62
+ priority: 499,
63
+ compile: function (element, attrs, transclude) {
64
+ return function ($scope, $element) {
65
+ var assert = function (condition, missing, found) {
66
+ if (!condition) {
67
+ throw new Error('You should add a ' + missing + ' attribute whenever you add a ' + found + ' attribute.');
68
+ }
69
+ };
70
+ assert(!attrs.translatePlural || attrs.translateN, 'translate-n', 'translate-plural');
71
+ assert(!attrs.translateN || attrs.translatePlural, 'translate-plural', 'translate-n');
72
+ assert(!attrs.ngIf, 'ng-if', 'translate');
73
+ assert(!attrs.ngSwitchWhen, 'ng-switch-when', 'translate');
74
+ var countFn = $parse(attrs.translateN);
75
+ transclude($scope, function (clone) {
76
+ var input = $.trim(clone.html());
77
+ clone.removeAttr('translate');
78
+ $element.replaceWith(clone);
79
+ return $scope.$watch(function () {
80
+ var prev = clone.html();
81
+ var translated;
82
+ if (attrs.translatePlural) {
83
+ translated = gettextCatalog.getPlural(countFn($scope), input, attrs.translatePlural);
84
+ } else {
85
+ translated = gettextCatalog.getString(input);
86
+ }
87
+ var interpolated = $interpolate(translated)($scope);
88
+ if (prev === interpolated) {
89
+ return;
90
+ }
91
+ return clone.html(interpolated);
92
+ });
93
+ });
94
+ };
95
+ }
96
+ };
97
+ }
98
+ ]);
99
+ angular.module('gettext').filter('translate', [
100
+ 'gettextCatalog',
101
+ '$interpolate',
102
+ '$parse',
103
+ function (gettextCatalog, $interpolate, $parse) {
104
+ return function (input) {
105
+ return gettextCatalog.getString(input);
106
+ };
107
+ }
108
+ ]);
109
+ angular.module('gettext').factory('gettextPlurals', function () {
110
+ return function (langCode, n) {
111
+ switch (langCode) {
112
+ case 'ay':
113
+ case 'bo':
114
+ case 'cgg':
115
+ case 'dz':
116
+ case 'fa':
117
+ case 'id':
118
+ case 'ja':
119
+ case 'jbo':
120
+ case 'ka':
121
+ case 'kk':
122
+ case 'km':
123
+ case 'ko':
124
+ case 'ky':
125
+ case 'lo':
126
+ case 'ms':
127
+ case 'my':
128
+ case 'sah':
129
+ case 'su':
130
+ case 'th':
131
+ case 'tt':
132
+ case 'ug':
133
+ case 'vi':
134
+ case 'wo':
135
+ case 'zh':
136
+ return 0;
137
+ case 'is':
138
+ return n % 10 != 1 || n % 100 == 11 ? 1 : 0;
139
+ case 'jv':
140
+ return n != 0 ? 1 : 0;
141
+ case 'mk':
142
+ return n == 1 || n % 10 == 1 ? 0 : 1;
143
+ case 'ach':
144
+ case 'ak':
145
+ case 'am':
146
+ case 'arn':
147
+ case 'br':
148
+ case 'fil':
149
+ case 'fr':
150
+ case 'gun':
151
+ case 'ln':
152
+ case 'mfe':
153
+ case 'mg':
154
+ case 'mi':
155
+ case 'oc':
156
+ case 'pt_BR':
157
+ case 'tg':
158
+ case 'ti':
159
+ case 'tr':
160
+ case 'uz':
161
+ case 'wa':
162
+ case 'zh':
163
+ return n > 1 ? 1 : 0;
164
+ case 'lv':
165
+ return n % 10 == 1 && n % 100 != 11 ? 0 : n != 0 ? 1 : 2;
166
+ case 'lt':
167
+ return n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2;
168
+ case 'be':
169
+ case 'bs':
170
+ case 'hr':
171
+ case 'ru':
172
+ case 'sr':
173
+ case 'uk':
174
+ return n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2;
175
+ case 'mnk':
176
+ return n == 0 ? 0 : n == 1 ? 1 : 2;
177
+ case 'ro':
178
+ return n == 1 ? 0 : n == 0 || n % 100 > 0 && n % 100 < 20 ? 1 : 2;
179
+ case 'pl':
180
+ return n == 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2;
181
+ case 'cs':
182
+ case 'sk':
183
+ return n == 1 ? 0 : n >= 2 && n <= 4 ? 1 : 2;
184
+ case 'sl':
185
+ return n % 100 == 1 ? 1 : n % 100 == 2 ? 2 : n % 100 == 3 || n % 100 == 4 ? 3 : 0;
186
+ case 'mt':
187
+ return n == 1 ? 0 : n == 0 || n % 100 > 1 && n % 100 < 11 ? 1 : n % 100 > 10 && n % 100 < 20 ? 2 : 3;
188
+ case 'gd':
189
+ return n == 1 || n == 11 ? 0 : n == 2 || n == 12 ? 1 : n > 2 && n < 20 ? 2 : 3;
190
+ case 'cy':
191
+ return n == 1 ? 0 : n == 2 ? 1 : n != 8 && n != 11 ? 2 : 3;
192
+ case 'kw':
193
+ return n == 1 ? 0 : n == 2 ? 1 : n == 3 ? 2 : 3;
194
+ case 'ga':
195
+ return n == 1 ? 0 : n == 2 ? 1 : n < 7 ? 2 : n < 11 ? 3 : 4;
196
+ case 'ar':
197
+ return n == 0 ? 0 : n == 1 ? 1 : n == 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 ? 4 : 5;
198
+ default:
199
+ return n != 1 ? 1 : 0;
200
+ }
201
+ };
202
+ });
@@ -0,0 +1,578 @@
1
+ /**
2
+ * @license AngularJS v1.2.0
3
+ * (c) 2010-2012 Google, Inc. http://angularjs.org
4
+ * License: MIT
5
+ */
6
+ (function(window, angular, undefined) {'use strict';
7
+
8
+ var $resourceMinErr = angular.$$minErr('$resource');
9
+
10
+ /**
11
+ * @ngdoc overview
12
+ * @name ngResource
13
+ * @description
14
+ *
15
+ * # ngResource
16
+ *
17
+ * The `ngResource` module provides interaction support with RESTful services
18
+ * via the $resource service.
19
+ *
20
+ * {@installModule resource}
21
+ *
22
+ * <div doc-module-components="ngResource"></div>
23
+ *
24
+ * See {@link ngResource.$resource `$resource`} for usage.
25
+ */
26
+
27
+ /**
28
+ * @ngdoc object
29
+ * @name ngResource.$resource
30
+ * @requires $http
31
+ *
32
+ * @description
33
+ * A factory which creates a resource object that lets you interact with
34
+ * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources.
35
+ *
36
+ * The returned resource object has action methods which provide high-level behaviors without
37
+ * the need to interact with the low level {@link ng.$http $http} service.
38
+ *
39
+ * Requires the {@link ngResource `ngResource`} module to be installed.
40
+ *
41
+ * @param {string} url A parametrized URL template with parameters prefixed by `:` as in
42
+ * `/user/:username`. If you are using a URL with a port number (e.g.
43
+ * `http://example.com:8080/api`), it will be respected.
44
+ *
45
+ * If you are using a url with a suffix, just add the suffix, like this:
46
+ * `$resource('http://example.com/resource.json')` or `$resource('http://example.com/:id.json')`
47
+ * or even `$resource('http://example.com/resource/:resource_id.:format')`
48
+ * If the parameter before the suffix is empty, :resource_id in this case, then the `/.` will be
49
+ * collapsed down to a single `.`. If you need this sequence to appear and not collapse then you
50
+ * can escape it with `/\.`.
51
+ *
52
+ * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in
53
+ * `actions` methods. If any of the parameter value is a function, it will be executed every time
54
+ * when a param value needs to be obtained for a request (unless the param was overridden).
55
+ *
56
+ * Each key value in the parameter object is first bound to url template if present and then any
57
+ * excess keys are appended to the url search query after the `?`.
58
+ *
59
+ * Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in
60
+ * URL `/path/greet?salutation=Hello`.
61
+ *
62
+ * If the parameter value is prefixed with `@` then the value of that parameter is extracted from
63
+ * the data object (useful for non-GET operations).
64
+ *
65
+ * @param {Object.<Object>=} actions Hash with declaration of custom action that should extend the
66
+ * default set of resource actions. The declaration should be created in the format of {@link
67
+ * ng.$http#usage_parameters $http.config}:
68
+ *
69
+ * {action1: {method:?, params:?, isArray:?, headers:?, ...},
70
+ * action2: {method:?, params:?, isArray:?, headers:?, ...},
71
+ * ...}
72
+ *
73
+ * Where:
74
+ *
75
+ * - **`action`** – {string} – The name of action. This name becomes the name of the method on
76
+ * your resource object.
77
+ * - **`method`** – {string} – HTTP request method. Valid methods are: `GET`, `POST`, `PUT`,
78
+ * `DELETE`, and `JSONP`.
79
+ * - **`params`** – {Object=} – Optional set of pre-bound parameters for this action. If any of
80
+ * the parameter value is a function, it will be executed every time when a param value needs to
81
+ * be obtained for a request (unless the param was overridden).
82
+ * - **`url`** – {string} – action specific `url` override. The url templating is supported just
83
+ * like for the resource-level urls.
84
+ * - **`isArray`** – {boolean=} – If true then the returned object for this action is an array,
85
+ * see `returns` section.
86
+ * - **`transformRequest`** –
87
+ * `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
88
+ * transform function or an array of such functions. The transform function takes the http
89
+ * request body and headers and returns its transformed (typically serialized) version.
90
+ * - **`transformResponse`** –
91
+ * `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
92
+ * transform function or an array of such functions. The transform function takes the http
93
+ * response body and headers and returns its transformed (typically deserialized) version.
94
+ * - **`cache`** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the
95
+ * GET request, otherwise if a cache instance built with
96
+ * {@link ng.$cacheFactory $cacheFactory}, this cache will be used for
97
+ * caching.
98
+ * - **`timeout`** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise} that
99
+ * should abort the request when resolved.
100
+ * - **`withCredentials`** - `{boolean}` - whether to set the `withCredentials` flag on the
101
+ * XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5
102
+ * requests with credentials} for more information.
103
+ * - **`responseType`** - `{string}` - see {@link
104
+ * https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType requestType}.
105
+ * - **`interceptor`** - `{Object=}` - The interceptor object has two optional methods -
106
+ * `response` and `responseError`. Both `response` and `responseError` interceptors get called
107
+ * with `http response` object. See {@link ng.$http $http interceptors}.
108
+ *
109
+ * @returns {Object} A resource "class" object with methods for the default set of resource actions
110
+ * optionally extended with custom `actions`. The default set contains these actions:
111
+ *
112
+ * { 'get': {method:'GET'},
113
+ * 'save': {method:'POST'},
114
+ * 'query': {method:'GET', isArray:true},
115
+ * 'remove': {method:'DELETE'},
116
+ * 'delete': {method:'DELETE'} };
117
+ *
118
+ * Calling these methods invoke an {@link ng.$http} with the specified http method,
119
+ * destination and parameters. When the data is returned from the server then the object is an
120
+ * instance of the resource class. The actions `save`, `remove` and `delete` are available on it
121
+ * as methods with the `$` prefix. This allows you to easily perform CRUD operations (create,
122
+ * read, update, delete) on server-side data like this:
123
+ * <pre>
124
+ var User = $resource('/user/:userId', {userId:'@id'});
125
+ var user = User.get({userId:123}, function() {
126
+ user.abc = true;
127
+ user.$save();
128
+ });
129
+ </pre>
130
+ *
131
+ * It is important to realize that invoking a $resource object method immediately returns an
132
+ * empty reference (object or array depending on `isArray`). Once the data is returned from the
133
+ * server the existing reference is populated with the actual data. This is a useful trick since
134
+ * usually the resource is assigned to a model which is then rendered by the view. Having an empty
135
+ * object results in no rendering, once the data arrives from the server then the object is
136
+ * populated with the data and the view automatically re-renders itself showing the new data. This
137
+ * means that in most case one never has to write a callback function for the action methods.
138
+ *
139
+ * The action methods on the class object or instance object can be invoked with the following
140
+ * parameters:
141
+ *
142
+ * - HTTP GET "class" actions: `Resource.action([parameters], [success], [error])`
143
+ * - non-GET "class" actions: `Resource.action([parameters], postData, [success], [error])`
144
+ * - non-GET instance actions: `instance.$action([parameters], [success], [error])`
145
+ *
146
+ * Success callback is called with (value, responseHeaders) arguments. Error callback is called
147
+ * with (httpResponse) argument.
148
+ *
149
+ * Class actions return empty instance (with additional properties below).
150
+ * Instance actions return promise of the action.
151
+ *
152
+ * The Resource instances and collection have these additional properties:
153
+ *
154
+ * - `$promise`: the {@link ng.$q promise} of the original server interaction that created this
155
+ * instance or collection.
156
+ *
157
+ * On success, the promise is resolved with the same resource instance or collection object,
158
+ * updated with data from server. This makes it easy to use in
159
+ * {@link ngRoute.$routeProvider resolve section of $routeProvider.when()} to defer view
160
+ * rendering until the resource(s) are loaded.
161
+ *
162
+ * On failure, the promise is resolved with the {@link ng.$http http response} object, without
163
+ * the `resource` property.
164
+ *
165
+ * - `$resolved`: `true` after first server interaction is completed (either with success or
166
+ * rejection), `false` before that. Knowing if the Resource has been resolved is useful in
167
+ * data-binding.
168
+ *
169
+ * @example
170
+ *
171
+ * # Credit card resource
172
+ *
173
+ * <pre>
174
+ // Define CreditCard class
175
+ var CreditCard = $resource('/user/:userId/card/:cardId',
176
+ {userId:123, cardId:'@id'}, {
177
+ charge: {method:'POST', params:{charge:true}}
178
+ });
179
+
180
+ // We can retrieve a collection from the server
181
+ var cards = CreditCard.query(function() {
182
+ // GET: /user/123/card
183
+ // server returns: [ {id:456, number:'1234', name:'Smith'} ];
184
+
185
+ var card = cards[0];
186
+ // each item is an instance of CreditCard
187
+ expect(card instanceof CreditCard).toEqual(true);
188
+ card.name = "J. Smith";
189
+ // non GET methods are mapped onto the instances
190
+ card.$save();
191
+ // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}
192
+ // server returns: {id:456, number:'1234', name: 'J. Smith'};
193
+
194
+ // our custom method is mapped as well.
195
+ card.$charge({amount:9.99});
196
+ // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}
197
+ });
198
+
199
+ // we can create an instance as well
200
+ var newCard = new CreditCard({number:'0123'});
201
+ newCard.name = "Mike Smith";
202
+ newCard.$save();
203
+ // POST: /user/123/card {number:'0123', name:'Mike Smith'}
204
+ // server returns: {id:789, number:'01234', name: 'Mike Smith'};
205
+ expect(newCard.id).toEqual(789);
206
+ * </pre>
207
+ *
208
+ * The object returned from this function execution is a resource "class" which has "static" method
209
+ * for each action in the definition.
210
+ *
211
+ * Calling these methods invoke `$http` on the `url` template with the given `method`, `params` and
212
+ * `headers`.
213
+ * When the data is returned from the server then the object is an instance of the resource type and
214
+ * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD
215
+ * operations (create, read, update, delete) on server-side data.
216
+
217
+ <pre>
218
+ var User = $resource('/user/:userId', {userId:'@id'});
219
+ var user = User.get({userId:123}, function() {
220
+ user.abc = true;
221
+ user.$save();
222
+ });
223
+ </pre>
224
+ *
225
+ * It's worth noting that the success callback for `get`, `query` and other methods gets passed
226
+ * in the response that came from the server as well as $http header getter function, so one
227
+ * could rewrite the above example and get access to http headers as:
228
+ *
229
+ <pre>
230
+ var User = $resource('/user/:userId', {userId:'@id'});
231
+ User.get({userId:123}, function(u, getResponseHeaders){
232
+ u.abc = true;
233
+ u.$save(function(u, putResponseHeaders) {
234
+ //u => saved user object
235
+ //putResponseHeaders => $http header getter
236
+ });
237
+ });
238
+ </pre>
239
+
240
+ * # Buzz client
241
+
242
+ Let's look at what a buzz client created with the `$resource` service looks like:
243
+ <doc:example>
244
+ <doc:source jsfiddle="false">
245
+ <script>
246
+ function BuzzController($resource) {
247
+ this.userId = 'googlebuzz';
248
+ this.Activity = $resource(
249
+ 'https://www.googleapis.com/buzz/v1/activities/:userId/:visibility/:activityId/:comments',
250
+ {alt:'json', callback:'JSON_CALLBACK'},
251
+ {
252
+ get:{method:'JSONP', params:{visibility:'@self'}},
253
+ replies: {method:'JSONP', params:{visibility:'@self', comments:'@comments'}}
254
+ }
255
+ );
256
+ }
257
+
258
+ BuzzController.prototype = {
259
+ fetch: function() {
260
+ this.activities = this.Activity.get({userId:this.userId});
261
+ },
262
+ expandReplies: function(activity) {
263
+ activity.replies = this.Activity.replies({userId:this.userId, activityId:activity.id});
264
+ }
265
+ };
266
+ BuzzController.$inject = ['$resource'];
267
+ </script>
268
+
269
+ <div ng-controller="BuzzController">
270
+ <input ng-model="userId"/>
271
+ <button ng-click="fetch()">fetch</button>
272
+ <hr/>
273
+ <div ng-repeat="item in activities.data.items">
274
+ <h1 style="font-size: 15px;">
275
+ <img src="{{item.actor.thumbnailUrl}}" style="max-height:30px;max-width:30px;"/>
276
+ <a href="{{item.actor.profileUrl}}">{{item.actor.name}}</a>
277
+ <a href ng-click="expandReplies(item)" style="float: right;">Expand replies:
278
+ {{item.links.replies[0].count}}</a>
279
+ </h1>
280
+ {{item.object.content | html}}
281
+ <div ng-repeat="reply in item.replies.data.items" style="margin-left: 20px;">
282
+ <img src="{{reply.actor.thumbnailUrl}}" style="max-height:30px;max-width:30px;"/>
283
+ <a href="{{reply.actor.profileUrl}}">{{reply.actor.name}}</a>: {{reply.content | html}}
284
+ </div>
285
+ </div>
286
+ </div>
287
+ </doc:source>
288
+ <doc:scenario>
289
+ </doc:scenario>
290
+ </doc:example>
291
+ */
292
+ angular.module('ngResource', ['ng']).
293
+ factory('$resource', ['$http', '$parse', '$q', function($http, $parse, $q) {
294
+ var DEFAULT_ACTIONS = {
295
+ 'get': {method:'GET'},
296
+ 'save': {method:'POST'},
297
+ 'query': {method:'GET', isArray:true},
298
+ 'remove': {method:'DELETE'},
299
+ 'delete': {method:'DELETE'}
300
+ };
301
+ var noop = angular.noop,
302
+ forEach = angular.forEach,
303
+ extend = angular.extend,
304
+ copy = angular.copy,
305
+ isFunction = angular.isFunction,
306
+ getter = function(obj, path) {
307
+ return $parse(path)(obj);
308
+ };
309
+
310
+ /**
311
+ * We need our custom method because encodeURIComponent is too aggressive and doesn't follow
312
+ * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path
313
+ * segments:
314
+ * segment = *pchar
315
+ * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
316
+ * pct-encoded = "%" HEXDIG HEXDIG
317
+ * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
318
+ * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
319
+ * / "*" / "+" / "," / ";" / "="
320
+ */
321
+ function encodeUriSegment(val) {
322
+ return encodeUriQuery(val, true).
323
+ replace(/%26/gi, '&').
324
+ replace(/%3D/gi, '=').
325
+ replace(/%2B/gi, '+');
326
+ }
327
+
328
+
329
+ /**
330
+ * This method is intended for encoding *key* or *value* parts of query component. We need a
331
+ * custom method because encodeURIComponent is too aggressive and encodes stuff that doesn't
332
+ * have to be encoded per http://tools.ietf.org/html/rfc3986:
333
+ * query = *( pchar / "/" / "?" )
334
+ * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
335
+ * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
336
+ * pct-encoded = "%" HEXDIG HEXDIG
337
+ * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
338
+ * / "*" / "+" / "," / ";" / "="
339
+ */
340
+ function encodeUriQuery(val, pctEncodeSpaces) {
341
+ return encodeURIComponent(val).
342
+ replace(/%40/gi, '@').
343
+ replace(/%3A/gi, ':').
344
+ replace(/%24/g, '$').
345
+ replace(/%2C/gi, ',').
346
+ replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));
347
+ }
348
+
349
+ function Route(template, defaults) {
350
+ this.template = template;
351
+ this.defaults = defaults || {};
352
+ this.urlParams = {};
353
+ }
354
+
355
+ Route.prototype = {
356
+ setUrlParams: function(config, params, actionUrl) {
357
+ var self = this,
358
+ url = actionUrl || self.template,
359
+ val,
360
+ encodedVal;
361
+
362
+ var urlParams = self.urlParams = {};
363
+ forEach(url.split(/\W/), function(param){
364
+ if (param === 'hasOwnProperty') {
365
+ throw $resourceMinErr('badname', "hasOwnProperty is not a valid parameter name.");
366
+ }
367
+ if (!(new RegExp("^\\d+$").test(param)) && param &&
368
+ (new RegExp("(^|[^\\\\]):" + param + "(\\W|$)").test(url))) {
369
+ urlParams[param] = true;
370
+ }
371
+ });
372
+ url = url.replace(/\\:/g, ':');
373
+
374
+ params = params || {};
375
+ forEach(self.urlParams, function(_, urlParam){
376
+ val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];
377
+ if (angular.isDefined(val) && val !== null) {
378
+ encodedVal = encodeUriSegment(val);
379
+ url = url.replace(new RegExp(":" + urlParam + "(\\W|$)", "g"), encodedVal + "$1");
380
+ } else {
381
+ url = url.replace(new RegExp("(\/?):" + urlParam + "(\\W|$)", "g"), function(match,
382
+ leadingSlashes, tail) {
383
+ if (tail.charAt(0) == '/') {
384
+ return tail;
385
+ } else {
386
+ return leadingSlashes + tail;
387
+ }
388
+ });
389
+ }
390
+ });
391
+
392
+ // strip trailing slashes and set the url
393
+ url = url.replace(/\/+$/, '');
394
+ // then replace collapse `/.` if found in the last URL path segment before the query
395
+ // E.g. `http://url.com/id./format?q=x` becomes `http://url.com/id.format?q=x`
396
+ url = url.replace(/\/\.(?=\w+($|\?))/, '.');
397
+ // replace escaped `/\.` with `/.`
398
+ config.url = url.replace(/\/\\\./, '/.');
399
+
400
+
401
+ // set params - delegate param encoding to $http
402
+ forEach(params, function(value, key){
403
+ if (!self.urlParams[key]) {
404
+ config.params = config.params || {};
405
+ config.params[key] = value;
406
+ }
407
+ });
408
+ }
409
+ };
410
+
411
+
412
+ function resourceFactory(url, paramDefaults, actions) {
413
+ var route = new Route(url);
414
+
415
+ actions = extend({}, DEFAULT_ACTIONS, actions);
416
+
417
+ function extractParams(data, actionParams){
418
+ var ids = {};
419
+ actionParams = extend({}, paramDefaults, actionParams);
420
+ forEach(actionParams, function(value, key){
421
+ if (isFunction(value)) { value = value(); }
422
+ ids[key] = value && value.charAt && value.charAt(0) == '@' ?
423
+ getter(data, value.substr(1)) : value;
424
+ });
425
+ return ids;
426
+ }
427
+
428
+ function defaultResponseInterceptor(response) {
429
+ return response.resource;
430
+ }
431
+
432
+ function Resource(value){
433
+ copy(value || {}, this);
434
+ }
435
+
436
+ forEach(actions, function(action, name) {
437
+ var hasBody = /^(POST|PUT|PATCH)$/i.test(action.method);
438
+
439
+ Resource[name] = function(a1, a2, a3, a4) {
440
+ var params = {}, data, success, error;
441
+
442
+ /* jshint -W086 */ /* (purposefully fall through case statements) */
443
+ switch(arguments.length) {
444
+ case 4:
445
+ error = a4;
446
+ success = a3;
447
+ //fallthrough
448
+ case 3:
449
+ case 2:
450
+ if (isFunction(a2)) {
451
+ if (isFunction(a1)) {
452
+ success = a1;
453
+ error = a2;
454
+ break;
455
+ }
456
+
457
+ success = a2;
458
+ error = a3;
459
+ //fallthrough
460
+ } else {
461
+ params = a1;
462
+ data = a2;
463
+ success = a3;
464
+ break;
465
+ }
466
+ case 1:
467
+ if (isFunction(a1)) success = a1;
468
+ else if (hasBody) data = a1;
469
+ else params = a1;
470
+ break;
471
+ case 0: break;
472
+ default:
473
+ throw $resourceMinErr('badargs',
474
+ "Expected up to 4 arguments [params, data, success, error], got {0} arguments",
475
+ arguments.length);
476
+ }
477
+ /* jshint +W086 */ /* (purposefully fall through case statements) */
478
+
479
+ var isInstanceCall = data instanceof Resource;
480
+ var value = isInstanceCall ? data : (action.isArray ? [] : new Resource(data));
481
+ var httpConfig = {};
482
+ var responseInterceptor = action.interceptor && action.interceptor.response ||
483
+ defaultResponseInterceptor;
484
+ var responseErrorInterceptor = action.interceptor && action.interceptor.responseError ||
485
+ undefined;
486
+
487
+ forEach(action, function(value, key) {
488
+ if (key != 'params' && key != 'isArray' && key != 'interceptor') {
489
+ httpConfig[key] = copy(value);
490
+ }
491
+ });
492
+
493
+ if (hasBody) httpConfig.data = data;
494
+ route.setUrlParams(httpConfig,
495
+ extend({}, extractParams(data, action.params || {}), params),
496
+ action.url);
497
+
498
+ var promise = $http(httpConfig).then(function(response) {
499
+ var data = response.data,
500
+ promise = value.$promise;
501
+
502
+ if (data) {
503
+ // Need to convert action.isArray to boolean in case it is undefined
504
+ // jshint -W018
505
+ if ( angular.isArray(data) !== (!!action.isArray) ) {
506
+ throw $resourceMinErr('badcfg', 'Error in resource configuration. Expected ' +
507
+ 'response to contain an {0} but got an {1}',
508
+ action.isArray?'array':'object', angular.isArray(data)?'array':'object');
509
+ }
510
+ // jshint +W018
511
+ if (action.isArray) {
512
+ value.length = 0;
513
+ forEach(data, function(item) {
514
+ value.push(new Resource(item));
515
+ });
516
+ } else {
517
+ copy(data, value);
518
+ value.$promise = promise;
519
+ }
520
+ }
521
+
522
+ value.$resolved = true;
523
+
524
+ response.resource = value;
525
+
526
+ return response;
527
+ }, function(response) {
528
+ value.$resolved = true;
529
+
530
+ (error||noop)(response);
531
+
532
+ return $q.reject(response);
533
+ });
534
+
535
+ promise = promise.then(
536
+ function(response) {
537
+ var value = responseInterceptor(response);
538
+ (success||noop)(value, response.headers);
539
+ return value;
540
+ },
541
+ responseErrorInterceptor);
542
+
543
+ if (!isInstanceCall) {
544
+ // we are creating instance / collection
545
+ // - set the initial promise
546
+ // - return the instance / collection
547
+ value.$promise = promise;
548
+ value.$resolved = false;
549
+
550
+ return value;
551
+ }
552
+
553
+ // instance call
554
+ return promise;
555
+ };
556
+
557
+
558
+ Resource.prototype['$' + name] = function(params, success, error) {
559
+ if (isFunction(params)) {
560
+ error = success; success = params; params = {};
561
+ }
562
+ var result = Resource[name](params, this, success, error);
563
+ return result.$promise || result;
564
+ };
565
+ });
566
+
567
+ Resource.bind = function(additionalParamDefaults){
568
+ return resourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);
569
+ };
570
+
571
+ return Resource;
572
+ }
573
+
574
+ return resourceFactory;
575
+ }]);
576
+
577
+
578
+ })(window, window.angular);