fat_free_crm 0.11.3 → 0.11.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of fat_free_crm might be problematic. Click here for more details.

Files changed (637) hide show
  1. data/.gitignore +1 -0
  2. data/.travis.yml +2 -2
  3. data/CHANGELOG +6 -1
  4. data/CONTRIBUTORS +40 -1
  5. data/Capfile +5 -0
  6. data/Gemfile +25 -6
  7. data/Gemfile.lock +128 -86
  8. data/README.md +23 -16
  9. data/{vendor → app}/assets/images/delete.png +0 -0
  10. data/app/assets/javascripts/admin/fields.js.coffee +62 -0
  11. data/app/assets/javascripts/application.js.erb +8 -1
  12. data/app/assets/javascripts/crm.js +44 -46
  13. data/app/assets/javascripts/crm_chosen.js.coffee +10 -7
  14. data/app/assets/javascripts/datepicker.js.coffee +15 -0
  15. data/app/assets/javascripts/format_buttons.js.coffee +48 -0
  16. data/app/assets/javascripts/{admin/field_groups.js.coffee → groups.js.coffee} +0 -0
  17. data/app/assets/javascripts/lists.js.coffee +1 -1
  18. data/app/assets/javascripts/search.js.coffee +56 -38
  19. data/app/assets/stylesheets/admin/{field_groups.css.scss → fields.css.scss} +4 -0
  20. data/app/assets/stylesheets/advanced_search.css.scss +79 -0
  21. data/app/assets/stylesheets/application.css.erb +4 -0
  22. data/app/assets/stylesheets/base.scss +3 -3
  23. data/app/assets/stylesheets/common.scss +72 -25
  24. data/app/assets/stylesheets/fields.scss +14 -0
  25. data/app/assets/stylesheets/format_buttons.css.scss +30 -0
  26. data/app/assets/stylesheets/groups.css.scss +3 -0
  27. data/app/assets/stylesheets/header.scss +7 -6
  28. data/{vendor/plugins/.gitkeep → app/assets/stylesheets/index_headers.css.scss} +0 -0
  29. data/app/assets/stylesheets/print.css.scss +12 -3
  30. data/app/assets/stylesheets/rails.scss +12 -3
  31. data/app/controllers/admin/application_controller.rb +1 -1
  32. data/app/controllers/admin/field_groups_controller.rb +2 -0
  33. data/app/controllers/admin/fields_controller.rb +41 -17
  34. data/app/controllers/admin/groups_controller.rb +70 -0
  35. data/app/controllers/admin/tags_controller.rb +1 -0
  36. data/app/controllers/admin/users_controller.rb +8 -7
  37. data/app/controllers/application_controller.rb +34 -5
  38. data/app/controllers/comments_controller.rb +2 -3
  39. data/app/controllers/entities/accounts_controller.rb +30 -37
  40. data/app/controllers/entities/campaigns_controller.rb +56 -29
  41. data/app/controllers/entities/contacts_controller.rb +24 -26
  42. data/app/controllers/entities/leads_controller.rb +38 -37
  43. data/app/controllers/entities/opportunities_controller.rb +28 -34
  44. data/app/controllers/entities_controller.rb +71 -43
  45. data/app/controllers/home_controller.rb +29 -27
  46. data/app/controllers/tasks_controller.rb +18 -17
  47. data/app/controllers/users_controller.rb +12 -8
  48. data/app/helpers/accounts_helper.rb +58 -16
  49. data/app/helpers/addresses_helper.rb +4 -1
  50. data/app/helpers/admin/fields_helper.rb +3 -4
  51. data/app/helpers/application_helper.rb +147 -100
  52. data/app/helpers/campaigns_helper.rb +2 -9
  53. data/app/helpers/fields_helper.rb +0 -1
  54. data/app/helpers/groups_helper.rb +2 -0
  55. data/app/helpers/home_helper.rb +11 -0
  56. data/app/helpers/leads_helper.rb +2 -9
  57. data/app/helpers/opportunities_helper.rb +2 -9
  58. data/app/helpers/{crm_tags_helper.rb → tags_helper.rb} +9 -8
  59. data/app/helpers/tasks_helper.rb +5 -21
  60. data/app/helpers/users_helper.rb +14 -7
  61. data/app/helpers/versions_helper.rb +46 -0
  62. data/app/inputs/date_time_input.rb +8 -25
  63. data/app/inputs/datepair_input.rb +77 -0
  64. data/app/inputs/datetimepair_input.rb +37 -0
  65. data/app/mailers/user_mailer.rb +10 -0
  66. data/app/models/entities/account.rb +18 -11
  67. data/app/models/entities/account_contact.rb +4 -3
  68. data/app/models/entities/account_opportunity.rb +0 -1
  69. data/app/models/entities/campaign.rb +6 -7
  70. data/app/models/entities/contact.rb +53 -25
  71. data/app/models/entities/contact_opportunity.rb +0 -1
  72. data/app/models/entities/lead.rb +24 -13
  73. data/app/models/entities/opportunity.rb +34 -16
  74. data/app/models/fields/custom_field.rb +29 -13
  75. data/app/models/fields/custom_field_date_pair.rb +58 -0
  76. data/app/models/fields/custom_field_datetime_pair.rb +28 -0
  77. data/app/models/fields/custom_field_pair.rb +54 -0
  78. data/app/models/fields/field.rb +60 -43
  79. data/app/models/fields/field_group.rb +0 -9
  80. data/app/models/observers/entity_observer.rb +29 -0
  81. data/app/models/observers/opportunity_observer.rb +3 -0
  82. data/app/models/polymorphic/address.rb +14 -0
  83. data/app/models/polymorphic/avatar.rb +13 -1
  84. data/app/models/polymorphic/email.rb +1 -1
  85. data/app/models/polymorphic/task.rb +14 -13
  86. data/app/models/setting.rb +14 -21
  87. data/app/models/users/ability.rb +25 -4
  88. data/app/models/users/group.rb +13 -0
  89. data/app/models/users/permission.rb +3 -1
  90. data/app/models/users/preference.rb +1 -2
  91. data/app/models/users/user.rb +25 -3
  92. data/app/views/accounts/_account.html.haml +5 -39
  93. data/app/views/accounts/_edit.html.haml +3 -2
  94. data/app/views/accounts/_index_brief.html.haml +32 -0
  95. data/app/views/accounts/_index_long.html.haml +42 -0
  96. data/app/views/accounts/_new.html.haml +3 -2
  97. data/app/views/accounts/_sidebar_index.html.haml +3 -4
  98. data/app/views/accounts/_sidebar_show.html.haml +2 -2
  99. data/app/views/accounts/_title_bar.html.haml +11 -0
  100. data/app/views/accounts/_top_section.html.haml +1 -1
  101. data/app/views/accounts/create.js.rjs +1 -2
  102. data/app/views/accounts/destroy.js.rjs +1 -1
  103. data/app/views/accounts/edit.js.rjs +0 -2
  104. data/app/views/accounts/index.html.haml +6 -13
  105. data/app/views/accounts/index.js.rjs +3 -1
  106. data/app/views/accounts/index.xls.builder +82 -0
  107. data/app/views/accounts/new.js.rjs +0 -2
  108. data/app/views/accounts/show.html.haml +17 -15
  109. data/app/views/accounts/show.js.erb +2 -0
  110. data/app/views/admin/custom_fields/_base_field.html.haml +21 -0
  111. data/app/views/admin/custom_fields/_check_boxes_field.html.haml +6 -0
  112. data/app/views/admin/custom_fields/_date_field.html.haml +14 -0
  113. data/app/views/admin/custom_fields/_date_pair_field.html.haml +21 -0
  114. data/app/views/admin/custom_fields/_datetime_field.html.haml +14 -0
  115. data/app/views/admin/custom_fields/_datetime_pair_field.html.haml +21 -0
  116. data/app/views/admin/custom_fields/_radio_field.html.haml +6 -0
  117. data/app/views/admin/custom_fields/_select_field.html.haml +25 -0
  118. data/app/views/admin/custom_fields/_string_field.html.haml +2 -0
  119. data/app/views/admin/field_groups/_field_group.html.haml +7 -5
  120. data/app/views/admin/field_groups/_top_section.html.haml +4 -3
  121. data/app/views/admin/field_groups/create.js.rjs +1 -2
  122. data/app/views/admin/fields/_field.html.haml +5 -3
  123. data/app/views/admin/fields/_form.html.haml +35 -0
  124. data/app/views/admin/fields/_subform.html.haml +6 -0
  125. data/app/views/admin/fields/create.js.erb +19 -0
  126. data/app/views/admin/fields/destroy.js.erb +9 -0
  127. data/app/views/admin/fields/edit.js.erb +1 -0
  128. data/app/views/admin/fields/index.html.haml +11 -8
  129. data/app/views/admin/fields/update.js.erb +13 -0
  130. data/app/views/admin/groups/_edit.html.haml +12 -0
  131. data/app/views/admin/groups/_form.html.haml +13 -0
  132. data/app/views/admin/groups/_group.html.haml +15 -0
  133. data/app/views/admin/groups/_new.html.haml +12 -0
  134. data/app/views/admin/groups/create.js.rjs +11 -0
  135. data/app/views/admin/{fields → groups}/destroy.js.rjs +3 -3
  136. data/app/views/admin/groups/edit.js.rjs +21 -0
  137. data/app/views/admin/groups/index.html.haml +18 -0
  138. data/app/views/admin/groups/index.js.rjs +2 -0
  139. data/app/views/admin/groups/new.js.rjs +9 -0
  140. data/app/views/admin/groups/show.html.haml +11 -0
  141. data/app/views/admin/groups/update.js.rjs +10 -0
  142. data/app/views/admin/users/_profile.html.haml +13 -1
  143. data/app/views/admin/users/_user.html.haml +7 -2
  144. data/app/views/admin/users/index.js.rjs +1 -0
  145. data/app/views/application/index.atom.builder +1 -1
  146. data/app/views/application/index.rss.builder +1 -1
  147. data/app/views/application/show.atom.builder +32 -0
  148. data/app/views/application/show.rss.builder +29 -0
  149. data/app/views/campaigns/_campaign.html.haml +5 -21
  150. data/app/views/campaigns/_edit.html.haml +3 -2
  151. data/app/views/campaigns/_index_brief.html.haml +15 -0
  152. data/app/views/campaigns/_index_long.html.haml +20 -0
  153. data/app/views/campaigns/_new.html.haml +4 -2
  154. data/app/views/campaigns/_sidebar_index.html.haml +3 -3
  155. data/app/views/campaigns/_title_bar.html.haml +11 -0
  156. data/app/views/campaigns/_top_section.html.haml +2 -2
  157. data/app/views/campaigns/create.js.rjs +1 -4
  158. data/app/views/campaigns/destroy.js.rjs +1 -1
  159. data/app/views/campaigns/edit.js.rjs +0 -4
  160. data/app/views/campaigns/index.html.haml +6 -13
  161. data/app/views/campaigns/index.js.rjs +3 -1
  162. data/app/views/campaigns/index.xls.builder +75 -0
  163. data/app/views/campaigns/new.js.rjs +0 -4
  164. data/app/views/campaigns/show.html.haml +17 -15
  165. data/app/views/campaigns/show.js.erb +2 -0
  166. data/app/views/campaigns/update.js.rjs +0 -2
  167. data/app/views/comments/_comment.html.haml +6 -5
  168. data/app/views/comments/_edit.html.haml +5 -5
  169. data/app/views/comments/_new.html.haml +6 -5
  170. data/app/views/comments/create.js.rjs +1 -1
  171. data/app/views/contacts/_contact.html.haml +5 -52
  172. data/app/views/contacts/_contacts.html.haml +1 -0
  173. data/app/views/contacts/_edit.html.haml +3 -2
  174. data/app/views/contacts/_index_brief.html.haml +25 -0
  175. data/app/views/contacts/_index_full.html.haml +57 -0
  176. data/app/views/contacts/_index_long.html.haml +43 -0
  177. data/app/views/contacts/_new.html.haml +4 -2
  178. data/app/views/contacts/_section_extra.html.haml +26 -0
  179. data/app/views/contacts/_section_general.html.haml +22 -0
  180. data/app/views/contacts/_sidebar_index.html.haml +0 -3
  181. data/app/views/contacts/_sidebar_show.html.haml +2 -10
  182. data/app/views/contacts/_title_bar.html.haml +11 -0
  183. data/app/views/contacts/_top_section.html.haml +1 -1
  184. data/app/views/contacts/create.js.rjs +1 -2
  185. data/app/views/contacts/destroy.js.rjs +1 -1
  186. data/app/views/contacts/edit.js.rjs +0 -2
  187. data/app/views/contacts/index.html.haml +6 -14
  188. data/app/views/contacts/index.js.rjs +3 -1
  189. data/app/views/contacts/index.xls.builder +102 -0
  190. data/app/views/contacts/new.js.rjs +0 -2
  191. data/app/views/contacts/show.html.haml +15 -15
  192. data/app/views/contacts/show.js.erb +2 -0
  193. data/app/views/entities/_basic_search.html.haml +22 -0
  194. data/app/views/entities/_permissions.html.haml +41 -0
  195. data/app/views/entities/_search.html.haml +15 -0
  196. data/app/views/entities/_section_custom_fields.html.haml +11 -0
  197. data/app/views/entities/_title_bar.html.haml +12 -0
  198. data/app/views/entities/attach.js.rjs +1 -1
  199. data/app/views/entities/opportunities.js.rjs +1 -1
  200. data/app/views/entities/versions.js.erb +3 -0
  201. data/app/views/fields/_edit_custom_field_group.html.haml +8 -0
  202. data/app/views/fields/_group.html.haml +11 -20
  203. data/app/views/fields/_group_table.html.haml +13 -0
  204. data/app/views/fields/_group_view.html.haml +7 -0
  205. data/app/views/fields/_groups.html.haml +1 -4
  206. data/app/views/fields/_sidebar_show.html.haml +5 -4
  207. data/app/views/home/_account.html.haml +29 -0
  208. data/app/views/home/_activity.html.haml +16 -6
  209. data/app/views/home/_opportunity.html.haml +41 -0
  210. data/app/views/home/_options.html.haml +1 -1
  211. data/app/views/home/_task.html.haml +46 -0
  212. data/app/views/home/index.html.haml +32 -1
  213. data/app/views/home/index.js.rjs +1 -0
  214. data/app/views/layouts/_header.html.haml +3 -3
  215. data/app/views/layouts/_sidebar.html.haml +1 -3
  216. data/app/views/layouts/_tabbed.html.haml +2 -3
  217. data/app/views/layouts/_tabless.html.haml +1 -1
  218. data/app/views/layouts/admin/_header.html.haml +1 -1
  219. data/app/views/layouts/application.html.haml +7 -8
  220. data/app/views/layouts/header.xls.builder +8 -0
  221. data/app/views/leads/_contact.html.haml +1 -2
  222. data/app/views/leads/_convert.html.haml +1 -2
  223. data/app/views/leads/_convert_permissions.html.haml +21 -11
  224. data/app/views/leads/_edit.html.haml +3 -2
  225. data/app/views/leads/_index_brief.html.haml +41 -0
  226. data/app/views/leads/_index_long.html.haml +62 -0
  227. data/app/views/leads/_lead.html.haml +5 -62
  228. data/app/views/leads/_new.html.haml +4 -2
  229. data/app/views/leads/_opportunity.html.haml +1 -1
  230. data/app/views/leads/_sidebar_index.html.haml +3 -3
  231. data/app/views/leads/_sidebar_show.html.haml +3 -3
  232. data/app/views/leads/_status.html.haml +1 -1
  233. data/app/views/leads/_title_bar.html.haml +16 -0
  234. data/app/views/leads/convert.js.rjs +0 -1
  235. data/app/views/leads/create.js.rjs +1 -2
  236. data/app/views/leads/destroy.js.rjs +1 -1
  237. data/app/views/leads/edit.js.rjs +0 -2
  238. data/app/views/leads/index.html.haml +6 -13
  239. data/app/views/leads/index.js.rjs +3 -1
  240. data/app/views/leads/index.xls.builder +100 -0
  241. data/app/views/leads/new.js.rjs +0 -2
  242. data/app/views/leads/promote.js.rjs +0 -1
  243. data/app/views/leads/show.html.haml +13 -18
  244. data/app/views/leads/show.js.erb +2 -0
  245. data/app/views/{shared/_lists.html.haml → lists/_sidebar.html.haml} +0 -0
  246. data/app/views/lists/create.js.rjs +1 -1
  247. data/app/views/opportunities/_edit.html.haml +3 -2
  248. data/app/views/opportunities/_index_brief.html.haml +29 -0
  249. data/app/views/opportunities/_index_long.html.haml +59 -0
  250. data/app/views/opportunities/_new.html.haml +4 -2
  251. data/app/views/opportunities/_opportunity.html.haml +5 -57
  252. data/app/views/opportunities/_sidebar_index.html.haml +3 -3
  253. data/app/views/opportunities/_sidebar_show.html.haml +2 -2
  254. data/app/views/opportunities/_title_bar.html.haml +11 -0
  255. data/app/views/opportunities/_top_section.html.haml +2 -2
  256. data/app/views/opportunities/create.js.rjs +4 -6
  257. data/app/views/opportunities/destroy.js.rjs +1 -1
  258. data/app/views/opportunities/edit.js.rjs +0 -3
  259. data/app/views/opportunities/index.html.haml +6 -14
  260. data/app/views/opportunities/index.js.rjs +3 -1
  261. data/app/views/opportunities/index.xls.builder +69 -0
  262. data/app/views/opportunities/new.js.rjs +1 -5
  263. data/app/views/opportunities/show.html.haml +14 -14
  264. data/app/views/opportunities/show.js.erb +2 -0
  265. data/app/views/opportunities/update.js.rjs +0 -1
  266. data/app/views/passwords/new.html.haml +1 -1
  267. data/app/views/shared/_add_comment.html.haml +8 -0
  268. data/app/views/shared/_address.html.haml +1 -1
  269. data/app/views/shared/_address_show.html.haml +1 -1
  270. data/app/views/shared/_edit_comment.html.haml +2 -2
  271. data/app/views/shared/_export.html.haml +2 -1
  272. data/app/views/shared/_paginate_with_per_page.html.haml +14 -0
  273. data/app/views/shared/_recently.html.haml +1 -1
  274. data/app/views/shared/_search.html.haml +1 -1
  275. data/app/views/shared/_tags.html.haml +1 -2
  276. data/app/views/shared/_tasks.html.haml +2 -2
  277. data/app/views/tasks/_completed.html.haml +3 -3
  278. data/app/views/tasks/_new.html.haml +1 -1
  279. data/app/views/tasks/_pending.html.haml +2 -3
  280. data/app/views/tasks/_sidebar_index.html.haml +2 -2
  281. data/app/views/tasks/_top_section.html.haml +5 -3
  282. data/app/views/tasks/create.js.rjs +3 -4
  283. data/app/views/tasks/edit.js.rjs +2 -4
  284. data/app/views/tasks/index.html.haml +1 -1
  285. data/app/views/tasks/index.xls.builder +47 -0
  286. data/app/views/tasks/new.js.rjs +0 -2
  287. data/app/views/tasks/update.js.rjs +0 -1
  288. data/app/views/user_mailer/assigned_entity_notification.html.haml +3 -0
  289. data/app/views/users/_user.html.haml +2 -2
  290. data/app/views/users/_user_report.html.haml +6 -0
  291. data/app/views/users/opportunities_overview.html.haml +16 -0
  292. data/app/views/users/show.html.haml +2 -3
  293. data/app/views/users/update.js.rjs +1 -1
  294. data/app/views/versions/_version.html.haml +4 -19
  295. data/app/views/versions/_version_item.html.haml +8 -0
  296. data/app/views/versions/_versions.html.haml +9 -9
  297. data/config/application.rb +10 -2
  298. data/config/deploy.example.rb +47 -0
  299. data/config/environments/development.rb +1 -0
  300. data/config/environments/production.rb +1 -3
  301. data/config/environments/staging.rb +1 -1
  302. data/config/initializers/action_mailer.rb +10 -8
  303. data/config/initializers/custom_fields.rb +21 -0
  304. data/config/initializers/gravatar.rb +7 -0
  305. data/config/initializers/paper_trail.rb +1 -0
  306. data/config/initializers/ransack.rb +15 -0
  307. data/config/initializers/simple_form.rb +1 -2
  308. data/config/initializers/views.rb +42 -0
  309. data/config/locales/cz_fat_free_crm.yml +0 -10
  310. data/config/locales/de_fat_free_crm.yml +23 -21
  311. data/config/locales/en-GB_fat_free_crm.yml +241 -25
  312. data/config/locales/en-US_fat_free_crm.yml +139 -57
  313. data/config/locales/en-US_ransack.yml +92 -0
  314. data/config/locales/es_fat_free_crm.yml +0 -6
  315. data/config/locales/fr-CA_fat_free_crm.yml +0 -6
  316. data/config/locales/fr_fat_free_crm.yml +3 -14
  317. data/config/locales/it_fat_free_crm.yml +0 -11
  318. data/config/locales/ja_fat_free_crm.yml +0 -10
  319. data/config/locales/pl_fat_free_crm.yml +0 -6
  320. data/config/locales/pt-BR_fat_free_crm.yml +0 -6
  321. data/config/locales/ru_fat_free_crm.yml +0 -9
  322. data/config/locales/sv-SE_fat_free_crm.yml +0 -10
  323. data/config/locales/th_fat_free_crm.yml +0 -6
  324. data/config/locales/zh-CN.yml +4 -0
  325. data/config/locales/zh-CN_fat_free_crm.yml +78 -47
  326. data/config/routes.rb +13 -0
  327. data/config/settings.default.yml +20 -20
  328. data/db/demo/addresses.yml +2 -2
  329. data/db/migrate/20100928030598_create_sessions.rb +5 -0
  330. data/db/migrate/20100928030627_acts_as_taggable_on_migration.rb +6 -6
  331. data/db/migrate/20111201030535_add_field_groups_klass_name.rb +2 -1
  332. data/db/migrate/20120406082136_create_groups.rb +19 -0
  333. data/db/migrate/20120510025219_add_not_null_constraints_for_timestamp_columns.rb +21 -0
  334. data/db/migrate/20120528102124_increase_length_of_version_events.rb +9 -0
  335. data/db/migrate/20120801032706_add_pair_id_to_fields.rb +5 -0
  336. data/db/migrate/20121003063155_add_settings_to_custom_fields.rb +5 -0
  337. data/db/migrate/20121221033947_fix_country_mapping.rb +32 -0
  338. data/db/schema.rb +25 -6
  339. data/fat_free_crm.gemspec +16 -13
  340. data/lib/fat_free_crm.rb +2 -0
  341. data/lib/fat_free_crm/comment_extensions.rb +23 -0
  342. data/lib/fat_free_crm/core_ext/array.rb +8 -2
  343. data/lib/fat_free_crm/fields.rb +24 -2
  344. data/lib/fat_free_crm/gem_dependencies.rb +7 -1
  345. data/lib/fat_free_crm/permissions.rb +47 -26
  346. data/lib/fat_free_crm/version.rb +1 -1
  347. data/lib/fat_free_crm/view_factory.rb +95 -0
  348. data/lib/plugins/country_select/lib/country_select.rb +393 -374
  349. data/lib/tasks/{plugins.rake → db/migrate.rake} +1 -1
  350. data/lib/tasks/{schema_upgrade.rake → db/schema.rake} +2 -1
  351. data/lib/tasks/{mail_processing.rake → ffcrm/comment_replies.rake} +2 -21
  352. data/lib/tasks/ffcrm/config.rake +33 -0
  353. data/lib/tasks/{demo.rake → ffcrm/demo.rake} +3 -2
  354. data/lib/tasks/ffcrm/dropbox.rake +42 -0
  355. data/lib/tasks/ffcrm/settings.rake +46 -0
  356. data/lib/tasks/{fat_free_crm.rake → ffcrm/setup.rake} +1 -39
  357. data/lib/tasks/ffcrm/update_data.rake +256 -0
  358. data/{acceptance → spec/acceptance}/acceptance_helper.rb +5 -4
  359. data/{acceptance → spec/acceptance}/accounts_spec.rb +36 -10
  360. data/spec/acceptance/admin/groups_spec.rb +26 -0
  361. data/spec/acceptance/admin/users_spec.rb +34 -0
  362. data/spec/acceptance/campaigns_spec.rb +101 -0
  363. data/spec/acceptance/contacts_spec.rb +101 -0
  364. data/spec/acceptance/dashboard_spec.rb +62 -0
  365. data/spec/acceptance/leads_spec.rb +109 -0
  366. data/spec/acceptance/opportunities_overview_spec.rb +82 -0
  367. data/spec/acceptance/opportunities_spec.rb +103 -0
  368. data/{acceptance → spec/acceptance}/support/browser.rb +0 -0
  369. data/{acceptance → spec/acceptance}/support/headless.rb +0 -0
  370. data/{acceptance → spec/acceptance}/support/helpers.rb +8 -1
  371. data/{acceptance → spec/acceptance}/support/maintain_sessions.rb +0 -0
  372. data/spec/acceptance/support/paths.rb +42 -0
  373. data/spec/acceptance/support/selector_helpers.rb +31 -0
  374. data/spec/acceptance/tasks_spec.rb +85 -0
  375. data/spec/controllers/admin/groups_controller_spec.rb +5 -0
  376. data/spec/controllers/admin/users_controller_spec.rb +2 -3
  377. data/spec/controllers/applications_controller_spec.rb +40 -0
  378. data/spec/controllers/comments_controller_spec.rb +5 -6
  379. data/spec/controllers/emails_controller_spec.rb +1 -2
  380. data/spec/controllers/entities/accounts_controller_spec.rb +65 -81
  381. data/spec/controllers/entities/campaigns_controller_spec.rb +69 -85
  382. data/spec/controllers/entities/contacts_controller_spec.rb +78 -95
  383. data/spec/controllers/entities/leads_controller_spec.rb +105 -127
  384. data/spec/controllers/entities/opportunities_controller_spec.rb +88 -103
  385. data/spec/controllers/entities_controller_spec.rb +39 -0
  386. data/spec/controllers/home_controller_spec.rb +101 -11
  387. data/spec/controllers/tasks_controller_spec.rb +27 -32
  388. data/spec/controllers/users_controller_spec.rb +95 -28
  389. data/spec/factories/account_factories.rb +2 -2
  390. data/spec/factories/opportunity_factories.rb +12 -4
  391. data/spec/factories/task_factories.rb +4 -0
  392. data/spec/factories/user_factories.rb +9 -2
  393. data/spec/helpers/application_helper_spec.rb +15 -1
  394. data/spec/helpers/groups_helper_spec.rb +15 -0
  395. data/spec/helpers/users_helper_spec.rb +26 -4
  396. data/spec/lib/comment_extensions_spec.rb +29 -0
  397. data/spec/lib/core_ext/{string.rb → string_spec.rb} +0 -1
  398. data/spec/lib/fields_spec.rb +104 -0
  399. data/spec/lib/permissions_spec.rb +144 -0
  400. data/spec/lib/view_factory_spec.rb +68 -0
  401. data/spec/mailers/subscription_mailer_spec.rb +18 -4
  402. data/spec/mailers/user_mailer_spec.rb +134 -0
  403. data/spec/models/entities/account_spec.rb +44 -4
  404. data/spec/models/entities/campaign_spec.rb +3 -4
  405. data/spec/models/entities/contact_spec.rb +45 -5
  406. data/spec/models/entities/lead_spec.rb +3 -4
  407. data/spec/models/entities/opportunity_spec.rb +105 -9
  408. data/spec/models/fields/custom_field_date_pair_spec.rb +106 -0
  409. data/spec/models/fields/custom_field_pair_spec.rb +94 -0
  410. data/spec/models/fields/custom_field_spec.rb +43 -23
  411. data/spec/models/fields/field_spec.rb +3 -5
  412. data/spec/models/observers/entity_observer_spec.rb +65 -0
  413. data/spec/models/polymorphic/task_spec.rb +74 -118
  414. data/spec/models/polymorphic/version_spec.rb +18 -18
  415. data/spec/models/users/group_spec.rb +5 -0
  416. data/spec/models/users/permission_spec.rb +18 -1
  417. data/spec/models/users/preference_spec.rb +5 -1
  418. data/spec/models/users/user_spec.rb +55 -8
  419. data/spec/shared/models.rb +54 -0
  420. data/spec/spec_helper.rb +82 -87
  421. data/spec/support/auth_macros.rb +2 -3
  422. data/spec/views/accounts/_edit.haml_spec.rb +1 -2
  423. data/spec/views/accounts/_new.haml_spec.rb +1 -2
  424. data/spec/views/accounts/create.rjs_spec.rb +1 -3
  425. data/spec/views/accounts/edit.rjs_spec.rb +3 -4
  426. data/spec/views/accounts/index.haml_spec.rb +9 -6
  427. data/spec/views/accounts/new.rjs_spec.rb +2 -9
  428. data/spec/views/accounts/show.haml_spec.rb +1 -2
  429. data/spec/views/accounts/update.rjs_spec.rb +2 -3
  430. data/spec/views/admin/users/_create.haml_spec.rb +1 -2
  431. data/spec/views/admin/users/create.rjs_spec.rb +1 -2
  432. data/spec/views/campaigns/_edit.haml_spec.rb +2 -3
  433. data/spec/views/campaigns/_new.haml_spec.rb +2 -3
  434. data/spec/views/campaigns/create.rjs_spec.rb +0 -3
  435. data/spec/views/campaigns/destroy.rjs_spec.rb +1 -2
  436. data/spec/views/campaigns/edit.rjs_spec.rb +3 -6
  437. data/spec/views/campaigns/index.haml_spec.rb +6 -3
  438. data/spec/views/campaigns/new.rjs_spec.rb +2 -13
  439. data/spec/views/campaigns/show.haml_spec.rb +4 -6
  440. data/spec/views/campaigns/update.rjs_spec.rb +2 -7
  441. data/spec/views/contacts/_edit.haml_spec.rb +6 -7
  442. data/spec/views/contacts/_new.haml_spec.rb +2 -3
  443. data/spec/views/contacts/create.rjs_spec.rb +1 -3
  444. data/spec/views/contacts/edit.rjs_spec.rb +3 -4
  445. data/spec/views/contacts/index.haml_spec.rb +6 -3
  446. data/spec/views/contacts/new.rjs_spec.rb +2 -11
  447. data/spec/views/contacts/show.haml_spec.rb +1 -2
  448. data/spec/views/contacts/update.rjs_spec.rb +2 -3
  449. data/spec/views/home/index.haml_spec.rb +6 -2
  450. data/spec/views/home/index.rjs_spec.rb +1 -2
  451. data/spec/views/home/options.rjs_spec.rb +1 -2
  452. data/spec/views/leads/_convert.haml_spec.rb +1 -2
  453. data/spec/views/leads/_edit.haml_spec.rb +2 -3
  454. data/spec/views/leads/_new.haml_spec.rb +2 -3
  455. data/spec/views/leads/_sidebar_show.haml_spec.rb +1 -2
  456. data/spec/views/leads/convert.rjs_spec.rb +3 -5
  457. data/spec/views/leads/edit.rjs_spec.rb +4 -5
  458. data/spec/views/leads/index.haml_spec.rb +6 -3
  459. data/spec/views/leads/new.rjs_spec.rb +2 -11
  460. data/spec/views/leads/promote.rjs_spec.rb +3 -5
  461. data/spec/views/leads/show.haml_spec.rb +1 -2
  462. data/spec/views/leads/update.rjs_spec.rb +2 -3
  463. data/spec/views/opportunities/_edit.haml_spec.rb +5 -6
  464. data/spec/views/opportunities/_new.haml_spec.rb +2 -4
  465. data/spec/views/opportunities/create.rjs_spec.rb +0 -2
  466. data/spec/views/opportunities/edit.rjs_spec.rb +3 -4
  467. data/spec/views/opportunities/index.haml_spec.rb +7 -4
  468. data/spec/views/opportunities/new.rjs_spec.rb +2 -12
  469. data/spec/views/opportunities/show.haml_spec.rb +1 -2
  470. data/spec/views/opportunities/update.rjs_spec.rb +2 -3
  471. data/spec/views/tasks/_edit.haml_spec.rb +1 -3
  472. data/spec/views/tasks/complete.rjs_spec.rb +2 -3
  473. data/spec/views/tasks/create.rjs_spec.rb +2 -2
  474. data/spec/views/tasks/edit.rjs_spec.rb +1 -2
  475. data/spec/views/tasks/new.rjs_spec.rb +1 -18
  476. data/spec/views/users/avatar.rjs_spec.rb +1 -2
  477. data/spec/views/users/change_password.rjs_spec.rb +1 -2
  478. data/spec/views/users/edit.rjs_spec.rb +1 -2
  479. data/spec/views/users/password.rjs_spec.rb +1 -1
  480. data/spec/views/users/update.rjs_spec.rb +1 -2
  481. data/spec/views/users/upload_avatar.rjs_spec.rb +6 -7
  482. data/vendor/assets/images/brief.png +0 -0
  483. data/vendor/assets/images/chosen-sprite.png +0 -0
  484. data/vendor/assets/images/full.png +0 -0
  485. data/vendor/assets/images/jquery-ui/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  486. data/vendor/assets/images/jquery-ui/ui-bg_flat_0_eeeeee_40x100.png +0 -0
  487. data/vendor/assets/images/jquery-ui/ui-bg_flat_100_ffffff_40x100.png +0 -0
  488. data/vendor/assets/images/jquery-ui/ui-bg_flat_25_3875d7_40x100.png +0 -0
  489. data/vendor/assets/images/jquery-ui/ui-bg_flat_55_ffffff_40x100.png +0 -0
  490. data/vendor/assets/images/jquery-ui/ui-bg_flat_65_3875d7_40x100.png +0 -0
  491. data/vendor/assets/images/jquery-ui/ui-bg_flat_75_ffffff_40x100.png +0 -0
  492. data/vendor/assets/images/jquery-ui/ui-bg_highlight-soft_50_dddddd_1x100.png +0 -0
  493. data/vendor/assets/images/jquery-ui/{ui-icons_ef8c08_256x240.png → ui-icons_0073ea_256x240.png} +0 -0
  494. data/vendor/assets/images/jquery-ui/ui-icons_466bb1_256x240.png +0 -0
  495. data/vendor/assets/images/jquery-ui/{ui-icons_ffd27a_256x240.png → ui-icons_ff0084_256x240.png} +0 -0
  496. data/vendor/assets/images/long.png +0 -0
  497. data/vendor/assets/javascripts/chosen-jquery.js +3 -0
  498. data/vendor/assets/javascripts/chosen-prototype.js +3 -0
  499. data/vendor/assets/javascripts/chosen.jquery.coffee +574 -0
  500. data/vendor/assets/javascripts/chosen.proto.coffee +580 -0
  501. data/vendor/assets/javascripts/jquery.disable.js +23 -0
  502. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery-ui-timepicker-addon.js +1882 -0
  503. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery-ui-timepicker-af.js +20 -0
  504. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery-ui-timepicker-ca.js +20 -0
  505. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery-ui-timepicker-cz.js +20 -0
  506. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery-ui-timepicker-de.js +20 -0
  507. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery-ui-timepicker-el.js +20 -0
  508. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery-ui-timepicker-es.js +20 -0
  509. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery-ui-timepicker-et.js +20 -0
  510. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery-ui-timepicker-fi.js +20 -0
  511. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery-ui-timepicker-fr-CA.js +20 -0
  512. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery-ui-timepicker-fr.js +20 -0
  513. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery-ui-timepicker-gl.js +20 -0
  514. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery-ui-timepicker-he.js +20 -0
  515. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery-ui-timepicker-hu.js +20 -0
  516. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery-ui-timepicker-id.js +20 -0
  517. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery-ui-timepicker-it.js +20 -0
  518. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery-ui-timepicker-ja.js +20 -0
  519. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery-ui-timepicker-ko.js +20 -0
  520. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery-ui-timepicker-lt.js +20 -0
  521. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery-ui-timepicker-nl.js +20 -0
  522. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery-ui-timepicker-no.js +20 -0
  523. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery-ui-timepicker-pl.js +20 -0
  524. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery-ui-timepicker-pt.js +20 -0
  525. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery-ui-timepicker-ro.js +20 -0
  526. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery-ui-timepicker-ru.js +20 -0
  527. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery-ui-timepicker-sk.js +20 -0
  528. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery-ui-timepicker-sv.js +20 -0
  529. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery-ui-timepicker-tr.js +20 -0
  530. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery-ui-timepicker-vi.js +20 -0
  531. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery-ui-timepicker-zh-CN.js +20 -0
  532. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery-ui-timepicker-zh-TW.js +20 -0
  533. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery.ui.datepicker-cz.js +23 -0
  534. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery.ui.datepicker-de.js +23 -0
  535. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery.ui.datepicker-en-GB.js +23 -0
  536. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery.ui.datepicker-es.js +23 -0
  537. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery.ui.datepicker-fr.js +23 -0
  538. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery.ui.datepicker-it.js +23 -0
  539. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery.ui.datepicker-ja.js +23 -0
  540. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery.ui.datepicker-pl.js +23 -0
  541. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery.ui.datepicker-pt-BR.js +23 -0
  542. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery.ui.datepicker-ru.js +23 -0
  543. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery.ui.datepicker-sv-SE.js +23 -0
  544. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery.ui.datepicker-th.js +23 -0
  545. data/vendor/assets/javascripts/jquery_ui_datepicker/jquery.ui.datepicker-zh-CN.js +23 -0
  546. data/vendor/assets/javascripts/lib/abstract-chosen.coffee +110 -0
  547. data/vendor/assets/javascripts/lib/select-parser.coffee +51 -0
  548. data/vendor/assets/stylesheets/chosen.css.sass +361 -0
  549. data/vendor/assets/stylesheets/{jquery-ui.custom.css.erb → jquery-ui.custom.css} +70 -70
  550. data/zeus.json +21 -0
  551. metadata +304 -140
  552. data/acceptance/support/database_cleaner.rb +0 -16
  553. data/acceptance/support/paths.rb +0 -9
  554. data/app/views/accounts/_options.html.haml +0 -20
  555. data/app/views/accounts/_permissions.html.haml +0 -24
  556. data/app/views/accounts/options.js.rjs +0 -10
  557. data/app/views/admin/fields/_edit.html.haml +0 -9
  558. data/app/views/admin/fields/_new.html.haml +0 -10
  559. data/app/views/admin/fields/_options.html.haml +0 -12
  560. data/app/views/admin/fields/_top_section.html.haml +0 -54
  561. data/app/views/admin/fields/create.js.rjs +0 -16
  562. data/app/views/admin/fields/edit.js.rjs +0 -35
  563. data/app/views/admin/fields/index.js.rjs +0 -6
  564. data/app/views/admin/fields/new.js.rjs +0 -8
  565. data/app/views/admin/fields/options.js.rjs +0 -10
  566. data/app/views/admin/fields/update.js.rjs +0 -17
  567. data/app/views/campaigns/_options.html.haml +0 -20
  568. data/app/views/campaigns/_permissions.html.haml +0 -24
  569. data/app/views/campaigns/options.js.rjs +0 -10
  570. data/app/views/contacts/_options.html.haml +0 -21
  571. data/app/views/contacts/_permissions.html.haml +0 -24
  572. data/app/views/contacts/options.js.rjs +0 -10
  573. data/app/views/entities/_advanced_search.html.haml +0 -12
  574. data/app/views/entities/_condition_fields.html.haml +0 -14
  575. data/app/views/entities/_grouping_fields.html.haml +0 -12
  576. data/app/views/entities/advanced_search.js.rjs +0 -9
  577. data/app/views/entities/versions.js.rjs +0 -3
  578. data/app/views/leads/_options.html.haml +0 -21
  579. data/app/views/leads/_permissions.html.haml +0 -28
  580. data/app/views/leads/options.js.rjs +0 -10
  581. data/app/views/opportunities/_options.html.haml +0 -20
  582. data/app/views/opportunities/_permissions.html.haml +0 -24
  583. data/app/views/opportunities/options.js.rjs +0 -10
  584. data/app/views/shared/_outline.html.haml +0 -9
  585. data/app/views/shared/_per_page.html.haml +0 -10
  586. data/app/views/shared/_sort_by.html.haml +0 -10
  587. data/config/initializers/cancan.rb +0 -151
  588. data/config/initializers/squeel.rb +0 -5
  589. data/public/blank_iframe.html +0 -2
  590. data/spec/views/accounts/options.rjs_spec.rb +0 -59
  591. data/spec/views/campaigns/options.rjs_spec.rb +0 -60
  592. data/spec/views/contacts/options.rjs_spec.rb +0 -61
  593. data/spec/views/leads/options.rjs_spec.rb +0 -61
  594. data/spec/views/opportunities/options.rjs_spec.rb +0 -60
  595. data/vendor/assets/images/jquery-ui/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  596. data/vendor/assets/images/jquery-ui/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  597. data/vendor/assets/images/jquery-ui/ui-bg_flat_10_000000_40x100.png +0 -0
  598. data/vendor/assets/images/jquery-ui/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  599. data/vendor/assets/images/jquery-ui/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  600. data/vendor/assets/images/jquery-ui/ui-bg_glass_65_ffffff_1x400.png +0 -0
  601. data/vendor/assets/images/jquery-ui/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  602. data/vendor/assets/images/jquery-ui/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  603. data/vendor/assets/images/jquery-ui/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  604. data/vendor/assets/images/jquery-ui/ui-icons_222222_256x240.png +0 -0
  605. data/vendor/assets/images/jquery-ui/ui-icons_228ef1_256x240.png +0 -0
  606. data/vendor/assets/javascripts/calendar_date_select/calendar_date_select.js +0 -446
  607. data/vendor/assets/javascripts/calendar_date_select/format_american.js +0 -35
  608. data/vendor/assets/javascripts/calendar_date_select/format_danish.js +0 -31
  609. data/vendor/assets/javascripts/calendar_date_select/format_db.js +0 -27
  610. data/vendor/assets/javascripts/calendar_date_select/format_euro_24hr.js +0 -7
  611. data/vendor/assets/javascripts/calendar_date_select/format_euro_24hr_ymd.js +0 -7
  612. data/vendor/assets/javascripts/calendar_date_select/format_finnish.js +0 -32
  613. data/vendor/assets/javascripts/calendar_date_select/format_french.js +0 -24
  614. data/vendor/assets/javascripts/calendar_date_select/format_hyphen_ampm.js +0 -37
  615. data/vendor/assets/javascripts/calendar_date_select/format_iso_date.js +0 -29
  616. data/vendor/assets/javascripts/calendar_date_select/format_italian.js +0 -24
  617. data/vendor/assets/javascripts/calendar_date_select/locale/ar.js +0 -10
  618. data/vendor/assets/javascripts/calendar_date_select/locale/da.js +0 -11
  619. data/vendor/assets/javascripts/calendar_date_select/locale/de.js +0 -11
  620. data/vendor/assets/javascripts/calendar_date_select/locale/es.js +0 -11
  621. data/vendor/assets/javascripts/calendar_date_select/locale/fi.js +0 -10
  622. data/vendor/assets/javascripts/calendar_date_select/locale/fr.js +0 -11
  623. data/vendor/assets/javascripts/calendar_date_select/locale/it.js +0 -9
  624. data/vendor/assets/javascripts/calendar_date_select/locale/ja.js +0 -11
  625. data/vendor/assets/javascripts/calendar_date_select/locale/nl.js +0 -11
  626. data/vendor/assets/javascripts/calendar_date_select/locale/pl.js +0 -11
  627. data/vendor/assets/javascripts/calendar_date_select/locale/pt.js +0 -11
  628. data/vendor/assets/javascripts/calendar_date_select/locale/ru.js +0 -10
  629. data/vendor/assets/javascripts/calendar_date_select/locale/sl.js +0 -11
  630. data/vendor/assets/javascripts/calendar_date_select/locale/sv.js +0 -9
  631. data/vendor/assets/stylesheets/calendar_date_select/blue.css +0 -130
  632. data/vendor/assets/stylesheets/calendar_date_select/default.css +0 -135
  633. data/vendor/assets/stylesheets/calendar_date_select/green.css +0 -142
  634. data/vendor/assets/stylesheets/calendar_date_select/plain.css +0 -128
  635. data/vendor/assets/stylesheets/calendar_date_select/red.css +0 -135
  636. data/vendor/assets/stylesheets/calendar_date_select/silver.css +0 -133
  637. data/vendor/plugins/.gitkeep~master +0 -0
@@ -8,13 +8,34 @@ class Ability
8
8
  entities = [Account, Campaign, Contact, Lead, Opportunity]
9
9
 
10
10
  can :create, :all
11
+ can :read, [User] # for search autocomplete
11
12
  can :manage, entities, :access => 'Public'
12
13
  can :manage, entities + [Task], :user_id => user.id
14
+ can :manage, entities + [Task], :assigned_to => user.id
15
+
16
+ #
17
+ # Due to an obscure bug (see https://github.com/ryanb/cancan/issues/213)
18
+ # we must switch on user.admin? here to avoid the nil constraints which
19
+ # activate the issue referred to above.
20
+ #
21
+ if user.admin?
22
+ can :manage, :all
23
+ else
24
+ # Group or User permissions
25
+ t = Permission.arel_table
26
+ scope = t[:user_id].eq(user.id)
13
27
 
14
- entities.each do |klass|
15
- permissions = user.permissions.where(:asset_type => klass.name)
16
- can :manage, klass, :id => permissions.map(&:asset_id)
17
- end
28
+ if (group_ids = user.group_ids).any?
29
+ scope = scope.or(t[:group_id].eq_any(group_ids))
30
+ end
31
+
32
+ entities.each do |klass|
33
+ if (asset_ids = Permission.where(scope.and(t[:asset_type].eq(klass.name))).value_of(:asset_id)).any?
34
+ can :manage, klass, :id => asset_ids
35
+ end
36
+ end
37
+ end # if user.admin?
38
+
18
39
  end
19
40
  end
20
41
  end
@@ -0,0 +1,13 @@
1
+ class Group < ActiveRecord::Base
2
+ has_and_belongs_to_many :users
3
+ has_many :permissions
4
+
5
+ attr_accessible :name, :user_ids
6
+
7
+ validates :name, :presence => true, :uniqueness => true
8
+
9
+ # TODO: Fix chosen bug that makes this necessary
10
+ def user_ids=(value)
11
+ super value.join.split(',')
12
+ end
13
+ end
@@ -29,8 +29,10 @@
29
29
 
30
30
  class Permission < ActiveRecord::Base
31
31
  belongs_to :user
32
+ belongs_to :group
32
33
  belongs_to :asset, :polymorphic => true
33
34
 
34
- validates_presence_of :user_id
35
+ validates_presence_of :user_id, :unless => :group_id?
36
+ validates_presence_of :group_id, :unless => :user_id?
35
37
  end
36
38
 
@@ -36,7 +36,7 @@ class Preference < ActiveRecord::Base
36
36
  return super(name) if name.to_s == "user_id" # get the value of belongs_to
37
37
 
38
38
  return cached_prefs[name.to_s] if cached_prefs.has_key?(name.to_s)
39
- cached_prefs[name.to_s] = if (pref = Preference.find_by_name_and_user_id(name.to_s, self.user.id))
39
+ cached_prefs[name.to_s] = if (self.user.present? && pref = Preference.find_by_name_and_user_id(name.to_s, self.user.id))
40
40
  Marshal.load(Base64.decode64(pref.value))
41
41
  end
42
42
  end
@@ -59,4 +59,3 @@ class Preference < ActiveRecord::Base
59
59
  end
60
60
 
61
61
  end
62
-
@@ -65,8 +65,10 @@ class User < ActiveRecord::Base
65
65
  has_many :leads
66
66
  has_many :contacts
67
67
  has_many :opportunities
68
+ has_many :assigned_opportunities, :class_name => 'Opportunity', :foreign_key => 'assigned_to'
68
69
  has_many :permissions, :dependent => :destroy
69
70
  has_many :preferences, :dependent => :destroy
71
+ has_and_belongs_to_many :groups
70
72
 
71
73
  has_paper_trail :ignore => [:last_request_at, :perishable_token]
72
74
 
@@ -77,14 +79,16 @@ class User < ActiveRecord::Base
77
79
 
78
80
  scope :text_search, lambda { |query|
79
81
  query = query.gsub(/[^\w\s\-\.'\p{L}]/u, '').strip
80
- where('upper(username) LIKE upper(:s) OR upper(first_name) LIKE upper(:s) OR upper(last_name) LIKE upper(:s)', :s => "#{query}%")
82
+ where('upper(username) LIKE upper(:s) OR upper(first_name) LIKE upper(:s) OR upper(last_name) LIKE upper(:s)', :s => "%#{query}%")
81
83
  }
82
84
 
83
85
  scope :my, lambda {
84
- current_ability = Ability.new(User.current_user)
85
- accessible_by(current_ability)
86
+ accessible_by(User.current_ability)
86
87
  }
87
88
 
89
+ scope :have_assigned_opportunities, joins("INNER JOIN opportunities ON users.id = opportunities.assigned_to").
90
+ where("opportunities.stage <> 'lost' AND opportunities.stage <> 'won'")
91
+
88
92
  acts_as_authentic do |c|
89
93
  c.session_class = Authentication
90
94
  c.validates_uniqueness_of_login_field_options = { :message => :username_taken }
@@ -146,6 +150,13 @@ class User < ActiveRecord::Base
146
150
  self.single_access_token ||= update_attribute(:single_access_token, Authlogic::Random.friendly_token)
147
151
  end
148
152
 
153
+ # Massage value when using Chosen select box which gives values like ["", "1,2,3"]
154
+ #----------------------------------------------------------------------------
155
+ def group_ids=(value)
156
+ value = value.join.split(',').map(&:to_i) if value.map{|v| v.to_s.include?(',')}.any?
157
+ super(value)
158
+ end
159
+
149
160
  private
150
161
 
151
162
  # Suspend newly created user if signup requires an approval.
@@ -170,4 +181,15 @@ class User < ActiveRecord::Base
170
181
  end
171
182
  artifacts == 0
172
183
  end
184
+
185
+ # Define class methods
186
+ #----------------------------------------------------------------------------
187
+ class << self
188
+
189
+ def current_ability
190
+ Ability.new(User.current_user)
191
+ end
192
+
193
+ end
194
+
173
195
  end
@@ -1,39 +1,5 @@
1
- - amount = account.opportunities.pipeline.map(&:weighted_amount).sum
2
- %li.highlight[account]
3
- - if account.category
4
- .strip{:class => account.category} #{t(account.category)}
5
- - else
6
- .strip{:style => "color: gray;"} #{t :other}
7
-
8
- %ul.tools
9
- = hook(:account_tools_before, self, :account => account)
10
-
11
- - if can?(:update, account)
12
- %li= link_to_edit(account)
13
-
14
- - if can?(:destroy, account)
15
- %li= link_to_delete(account)
16
-
17
- .indent
18
- = link_to(account.name, account)
19
- - if amount != 0.0
20
- %span.amount= number_to_currency(amount, :precision => 0)
21
- &ndash;
22
- %tt
23
- = account.location << ", " unless account.location.blank?
24
- = t(:added_by, :time_ago => time_ago_in_words(account.created_at), :user => (account.user.id == @current_user.id ? t(:me) : account.user.full_name)) << " | "
25
- = t('pluralize.contact', account.contacts.count) << " | "
26
- = t('pluralize.opportunity', account.opportunities.count)
27
-
28
- - unless @current_user.preference[:accounts_outline] == "brief"
29
- %dt
30
- = stars_for(account)
31
- = " | ".html_safe << link_to(account.website, account.website.to_url) if account.website.present?
32
- = " | ".html_safe << link_to_email(account.email) if account.email.present?
33
- = " | ".html_safe << t(:phone_small) << ": " << (account.toll_free_phone? ? account.toll_free_phone : account.phone) if account.toll_free_phone? || account.phone?
34
-
35
- - if account.tag_list.present?
36
- %dt
37
- .tags= tags_for_index(account)
38
-
39
- = hook(:account_bottom, self, :account => account)
1
+ - if (params['controller'] == 'accounts') and (template = template_for_current_view).present?
2
+ = render(template, :account => account)
3
+ - else
4
+ -# default view
5
+ = render 'accounts/index_brief', :account => account
@@ -6,9 +6,10 @@
6
6
  = f.error_messages :object_name => t('account')
7
7
 
8
8
  = render "accounts/top_section", :f => f, :edit => true
9
+ = render "fields/edit_custom_field_group", :f => f, :edit => true
9
10
  = render "accounts/contact_info", :f => f, :edit => true
10
- = render "fields/groups", :f => f, :edit => true
11
- = render "accounts/permissions", :f => f, :edit => true
11
+ = render "fields/groups", :f => f, :edit => true
12
+ = render "entities/permissions", :f => f, :edit => true, :entity => @account
12
13
 
13
14
  .buttonbar
14
15
  - if Setting.compound_address
@@ -0,0 +1,32 @@
1
+ - amount = account.opportunities.pipeline.map(&:weighted_amount).sum
2
+ %li.highlight[account]
3
+ - if account.category
4
+ .strip{:class => account.category} #{t(account.category)}
5
+ - else
6
+ .strip{:style => "color: gray;"} #{t :other}
7
+
8
+ %ul.tools
9
+ = hook(:account_tools_before, self, :account => account)
10
+
11
+ - if can?(:update, account)
12
+ %li= link_to_edit(account)
13
+
14
+ - if can?(:destroy, account)
15
+ %li= link_to_delete(account)
16
+
17
+ .indent
18
+ = link_to(account.name, account)
19
+ - if amount != 0.0
20
+ %span.amount= number_to_currency(amount, :precision => 0)
21
+ &ndash;
22
+ %tt
23
+ = account.location << ", " unless account.location.blank?
24
+ - user_name = account.user_id == current_user.id ? t(:me) : account.user.try(:full_name)
25
+ - if user_name
26
+ = t(:added_by, :time_ago => time_ago_in_words(account.created_at), :user => user_name) << " | "
27
+ - else
28
+ = t(:added_ago, :value => time_ago_in_words(account.created_at)) << " | "
29
+ = t('pluralize.contact', account.contacts.count) << " | "
30
+ = t('pluralize.opportunity', account.opportunities.count)
31
+
32
+ = hook(:account_bottom, self, :account => account)
@@ -0,0 +1,42 @@
1
+ - amount = account.opportunities.pipeline.map(&:weighted_amount).sum
2
+ %li.highlight[account]
3
+ - if account.category
4
+ .strip{:class => account.category} #{t(account.category)}
5
+ - else
6
+ .strip{:style => "color: gray;"} #{t :other}
7
+
8
+ %ul.tools
9
+ = hook(:account_tools_before, self, :account => account)
10
+
11
+ - if can?(:update, account)
12
+ %li= link_to_edit(account)
13
+
14
+ - if can?(:destroy, account)
15
+ %li= link_to_delete(account)
16
+
17
+ .indent
18
+ = link_to(account.name, account)
19
+ - if amount != 0.0
20
+ %span.amount= number_to_currency(amount, :precision => 0)
21
+ &ndash;
22
+ %tt
23
+ = account.location << ", " unless account.location.blank?
24
+ - user_name = account.user_id == current_user.id ? t(:me) : account.user.try(:full_name)
25
+ - if user_name
26
+ = t(:added_by, :time_ago => time_ago_in_words(account.created_at), :user => user_name) << " | "
27
+ - else
28
+ = t(:added_ago, :value => time_ago_in_words(account.created_at)) << " | "
29
+ = t('pluralize.contact', account.contacts.count) << " | "
30
+ = t('pluralize.opportunity', account.opportunities.count)
31
+
32
+ %dt
33
+ = stars_for(account)
34
+ = " | ".html_safe << link_to(account.website, account.website.to_url) if account.website.present?
35
+ = " | ".html_safe << link_to_email(account.email) if account.email.present?
36
+ = " | ".html_safe << t(:phone_small) << ": " << (account.toll_free_phone? ? account.toll_free_phone : account.phone) if account.toll_free_phone? || account.phone?
37
+
38
+ - if account.tag_list.present?
39
+ %dt
40
+ .tags= tags_for_index(account)
41
+
42
+ = hook(:account_bottom, self, :account => account)
@@ -5,9 +5,11 @@
5
5
  = f.error_messages :object_name => t('account')
6
6
 
7
7
  = render "accounts/top_section", :f => f
8
+ = render "fields/edit_custom_field_group", :f => f
9
+ = render "shared/add_comment", :f => f
8
10
  = render "accounts/contact_info", :f => f
9
11
  = render "fields/groups", :f => f
10
- = render "accounts/permissions", :f => f
12
+ = render "entities/permissions", :f => f, :entity => @account
11
13
 
12
14
  .buttonbar
13
15
  - if Setting.compound_address
@@ -16,4 +18,3 @@
16
18
  = f.submit t(:create_account)
17
19
  #{t :or}
18
20
  = link_to_cancel new_account_path
19
-
@@ -1,17 +1,16 @@
1
1
  .filters#filters
2
- = render "shared/search"
3
- = hook(:index_account_sidebar_bottom, self)
2
+ .caption= t :account_categories
4
3
  - Setting.account_category.each do |key|
5
4
  .check_box{:style => "border-bottom: 1px silver dotted;"}
6
5
  %div{:style => "float:right;"}
7
6
  = @account_category_total[key]
8
- = account_category_checbox(key, @account_category_total[key])
7
+ = account_category_checkbox(key, @account_category_total[key])
9
8
  = label_tag(key, t(key))
10
9
 
11
10
  .check_box{:style => "border-bottom: 1px silver dotted;"}
12
11
  %div{:style => "float:right;"}
13
12
  = @account_category_total[:other]
14
- = account_category_checbox("other", @account_category_total[:other])
13
+ = account_category_checkbox("other", @account_category_total[:other])
15
14
  = label_tag(:other, t(:other))
16
15
 
17
16
  .check_box
@@ -40,8 +40,8 @@
40
40
  %li
41
41
  %span{:style => "float:right;"}= stars_for(@account)
42
42
  %tt #{t :rating}:
43
- %li.last
44
- %dt= truncate((@account.assigned_to ? @account.assignee.full_name : @account.user.full_name), :length => 16)
43
+ %li
44
+ %dt= @account.assigned_to ? truncate(@account.assignee.full_name, :length => 16) : nil
45
45
  %tt #{t :assigned_to}:
46
46
 
47
47
  - unless @account.background_info.blank?
@@ -0,0 +1,11 @@
1
+ #confirm{ hidden }
2
+ .title_tools#menu
3
+ = link_to_inline(:edit_account, edit_account_path(@account), :text => t(:edit)) + " | "
4
+ = link_to_function(t(:delete) + '?', confirm_delete(@account))
5
+ .title_tools#buttons
6
+ = view_buttons
7
+ .title#edit_account_title
8
+ = h(@account.name)
9
+ = image_tag("loading.gif", :size => :thumb, :id => "loading", :style => "display: none;")
10
+
11
+ %div#edit_account{ hidden }
@@ -8,7 +8,7 @@
8
8
  %tr
9
9
  %td
10
10
  .label #{t :assigned_to}:
11
- = user_select(:account)
11
+ = user_select(:account, User.except(current_user), current_user)
12
12
  %td= spacer
13
13
  %td
14
14
  .label #{t :category}:
@@ -5,11 +5,10 @@ if @account.valid?
5
5
  page.insert_html :top, :accounts, :partial => "account", :collection => [ @account ]
6
6
  page[dom_id(@account)].visual_effect :highlight, :duration => 1.5
7
7
  page << refresh_sidebar(:index, :filters)
8
- page[:paginate].replace_html :partial => "shared/paginate"
8
+ page[:paginate].replace_html :partial => "shared/paginate_with_per_page"
9
9
  page.call "crm.flick", :empty, :remove
10
10
  else
11
11
  page[:create_account].replace_html :partial => "new"
12
- page.call "crm.init_chosen_fields"
13
12
  page[:create_account].visual_effect :shake, :duration => 0.25, :distance => 6
14
13
  page[:account_name].focus
15
14
  end
@@ -1,3 +1,3 @@
1
1
  page[dom_id(@account)].visual_effect :blind_up, :duration => 0.25
2
2
  page << refresh_sidebar(:index, :filters)
3
- page[:paginate].replace_html :partial => "shared/paginate"
3
+ page[:paginate].replace_html :partial => "shared/paginate_with_per_page"
@@ -22,11 +22,9 @@ else # <---------------------------------------- Show [Edit Account] form.
22
22
  page.call "crm.highlight_off", id # Disable onMouseOver for the list item.
23
23
  page.call "crm.hide_form", :create_account # Hide [Create Account] form if any.
24
24
  page[id].replace_html :partial => "edit" # Show [Edit Account] form.
25
- page.call "crm.init_chosen_fields"
26
25
 
27
26
  elsif params[:cancel].false? # Called from title of the account landing page...
28
27
  page[:edit_account].replace_html :partial => "edit"
29
- page.call "crm.init_chosen_fields"
30
28
  page.call "crm.flip_form", :edit_account
31
29
  page.call "crm.set_title", :edit_account, "#{t :edit} #{@account.name}"
32
30
  end
@@ -1,25 +1,18 @@
1
1
  = styles_for :account
2
2
 
3
- .title_tools
4
- = link_to_inline(:create_account, new_account_path, :text => t(:create_account)) << " | "
5
- - if Setting.advanced_search_enabled
6
- = link_to_inline(:advanced_search, advanced_search_accounts_path, :text => t(:advanced_search)) << " | "
7
- = link_to_inline(:options, options_accounts_path, :text=> t(:options))
3
+ = render 'entities/title_bar'
8
4
 
9
- .title
10
- %span#create_account_title #{t :accounts}
11
- = image_tag("loading.gif", :size => :thumb, :id => "loading", :style => "display: none;")
12
- .remote#options{ hidden }
13
- .remote#advanced_search{ hidden_if(!params[:q]) }
14
- - if params[:q]
15
- = render :partial => "advanced_search"
16
5
  .remote#create_account{ hidden }
17
6
 
7
+ = render 'search'
8
+
9
+ .remote#options{ hidden }
10
+
18
11
  .list#accounts
19
12
  - if @accounts.any?
20
13
  = render @accounts
21
14
  - else
22
15
  = render "shared/empty"
23
16
 
24
- #paginate= render "shared/paginate"
17
+ #paginate= render "shared/paginate_with_per_page"
25
18
  #export= render "shared/export"
@@ -3,4 +3,6 @@ if @accounts.any?
3
3
  else
4
4
  page[:accounts].replace_html :partial => "shared/empty"
5
5
  end
6
- page[:paginate].replace_html :partial => "shared/paginate"
6
+ page[:paginate].replace_html :partial => "shared/paginate_with_per_page"
7
+ page[:export].replace_html :partial => "shared/export"
8
+ page[:search_results_count].replace_html :text => t('search_results_count', :count => @search_results_count)
@@ -0,0 +1,82 @@
1
+ xml.Worksheet 'ss:Name' => I18n.t(:tab_accounts) do
2
+ xml.Table do
3
+ unless @accounts.empty?
4
+ # Header.
5
+ xml.Row do
6
+ heads = [I18n.t('user'),
7
+ I18n.t('assigned_to'),
8
+ I18n.t('name'),
9
+ I18n.t('email'),
10
+ I18n.t('phone'),
11
+ I18n.t('fax'),
12
+ I18n.t('website'),
13
+ I18n.t('background_info'),
14
+ I18n.t('access'),
15
+ I18n.t('phone_toll_free'),
16
+ I18n.t('rating'),
17
+ I18n.t('category'),
18
+ I18n.t('date_created'),
19
+ I18n.t('date_updated'),
20
+ I18n.t('street1'),
21
+ I18n.t('street2'),
22
+ I18n.t('city'),
23
+ I18n.t('state'),
24
+ I18n.t('zipcode'),
25
+ I18n.t('country'),
26
+ I18n.t('address')]
27
+
28
+ # Append custom field labels to header
29
+ Account.fields.each do |field|
30
+ heads << field.label
31
+ end
32
+
33
+ heads.each do |head|
34
+ xml.Cell do
35
+ xml.Data head,
36
+ 'ss:Type' => 'String'
37
+ end
38
+ end
39
+ end
40
+
41
+ # Account rows.
42
+ @accounts.each do |account|
43
+ xml.Row do
44
+ address = account.billing_address
45
+ data = [account.user.try(:name),
46
+ account.assignee.try(:name),
47
+ account.name,
48
+ account.email,
49
+ account.phone,
50
+ account.fax,
51
+ account.website,
52
+ account.background_info,
53
+ account.access,
54
+ account.toll_free_phone,
55
+ account.rating,
56
+ account.category,
57
+ account.created_at,
58
+ account.updated_at,
59
+ address.try(:street1),
60
+ address.try(:street2),
61
+ address.try(:city),
62
+ address.try(:state),
63
+ address.try(:zipcode),
64
+ address.try(:country),
65
+ address.try(:full_address)]
66
+
67
+ # Append custom field values.
68
+ Account.fields.each do |field|
69
+ data << account.send(field.name)
70
+ end
71
+
72
+ data.each do |value|
73
+ xml.Cell do
74
+ xml.Data value,
75
+ 'ss:Type' => "#{value.respond_to?(:abs) ? 'Number' : 'String'}"
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end