droom 0.0.1 → 0.2.1

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.
Files changed (459) hide show
  1. data/README.md +2 -2
  2. data/app/assets/images/droom/Untitled-1.png +0 -0
  3. data/app/assets/images/droom/acceptance.png +0 -0
  4. data/app/assets/images/droom/add.png +0 -0
  5. data/app/assets/images/droom/asterisk.png +0 -0
  6. data/app/assets/images/droom/asterisk_up.png +0 -0
  7. data/app/assets/images/droom/checkboxes.png +0 -0
  8. data/app/assets/images/droom/clear.png +0 -0
  9. data/app/assets/images/droom/cog.png +0 -0
  10. data/app/assets/images/droom/copy.png +0 -0
  11. data/app/assets/images/droom/copy_to_dropbox.png +0 -0
  12. data/app/assets/images/droom/crosses.png +0 -0
  13. data/app/assets/images/droom/dark_scrap_icons.png +0 -0
  14. data/app/assets/images/droom/defilter.png +0 -0
  15. data/app/assets/images/droom/delete.png +0 -0
  16. data/app/assets/images/droom/dropbox.png +0 -0
  17. data/app/assets/images/droom/dropbox_button.png +0 -0
  18. data/app/assets/images/droom/dropbox_button_small.png +0 -0
  19. data/app/assets/images/droom/edit.png +0 -0
  20. data/app/assets/images/droom/expand.png +0 -0
  21. data/app/assets/images/droom/expander.png +0 -0
  22. data/app/assets/images/droom/folder.png +0 -0
  23. data/app/assets/images/droom/image_box.png +0 -0
  24. data/app/assets/images/droom/in_dropbox.png +0 -0
  25. data/app/assets/images/droom/integration_buttons.png +0 -0
  26. data/app/assets/images/droom/leftright.png +0 -0
  27. data/app/assets/images/droom/manage.png +0 -0
  28. data/app/assets/images/droom/medium_object_icons.png +0 -0
  29. data/app/assets/images/droom/object_icons.png +0 -0
  30. data/app/assets/images/droom/playable.png +0 -0
  31. data/app/assets/images/droom/revoke.png +0 -0
  32. data/app/assets/images/droom/scrap_icons.png +0 -0
  33. data/app/assets/images/droom/search.png +0 -0
  34. data/app/assets/images/droom/small_asterisk.png +0 -0
  35. data/app/assets/images/droom/small_cog.png +0 -0
  36. data/app/assets/images/droom/small_download.png +0 -0
  37. data/app/assets/images/droom/small_image_box.png +0 -0
  38. data/app/assets/images/droom/smalladd.png +0 -0
  39. data/app/assets/images/droom/smallarrows.png +0 -0
  40. data/app/assets/images/droom/smallcopy.png +0 -0
  41. data/app/assets/images/droom/smalldelete.png +0 -0
  42. data/app/assets/images/droom/smalldownload.png +0 -0
  43. data/app/assets/images/droom/smalledit.png +0 -0
  44. data/app/assets/images/droom/smallmanage.png +0 -0
  45. data/app/assets/images/droom/star.png +0 -0
  46. data/app/assets/images/droom/symbols.png +0 -0
  47. data/app/assets/images/droom/tinyarrows.png +0 -0
  48. data/app/assets/images/droom/to_dropbox.png +0 -0
  49. data/app/assets/images/droom/twisty.png +0 -0
  50. data/app/assets/images/droom/youtube_icon.png +0 -0
  51. data/app/assets/javascripts/droom.js.coffee +62 -65
  52. data/app/assets/javascripts/droom/actions.js.coffee +492 -0
  53. data/app/assets/javascripts/droom/ajax.js.coffee +84 -0
  54. data/app/assets/javascripts/droom/{lib/extensions.js.coffee → extensions.js.coffee} +22 -15
  55. data/app/assets/javascripts/droom/lib/ZeroClipboard.js +334 -0
  56. data/app/assets/javascripts/droom/lib/ZeroClipboard.swf +0 -0
  57. data/app/assets/javascripts/droom/lib/ZeroClipboard10.swf +0 -0
  58. data/app/assets/javascripts/droom/map.js.coffee +124 -86
  59. data/app/assets/javascripts/droom/popups.js.coffee +252 -0
  60. data/app/assets/javascripts/droom/stream.js.coffee +92 -0
  61. data/app/assets/javascripts/droom/utilities.js.coffee +120 -0
  62. data/app/assets/javascripts/droom/widgets.js.coffee +1209 -0
  63. data/app/assets/stylesheets/_definitions.css.sass +189 -0
  64. data/app/assets/stylesheets/droom.css.sass +1429 -376
  65. data/app/assets/stylesheets/lib/_kalendae.css.sass +2 -5
  66. data/app/assets/stylesheets/lib/_popups.css.sass +86 -0
  67. data/app/assets/stylesheets/lib/_toolbar.css.sass +17 -11
  68. data/app/controllers/droom/agenda_categories_controller.rb +24 -0
  69. data/app/controllers/droom/calendars_controller.rb +29 -0
  70. data/app/controllers/droom/confirmations_controller.rb +38 -0
  71. data/app/controllers/droom/dashboard_controller.rb +2 -0
  72. data/app/controllers/droom/documents_controller.rb +42 -51
  73. data/app/controllers/droom/dropbox_tokens_controller.rb +61 -0
  74. data/app/controllers/droom/engine_controller.rb +8 -23
  75. data/app/controllers/droom/events_controller.rb +39 -27
  76. data/app/controllers/droom/folders_controller.rb +106 -0
  77. data/app/controllers/droom/group_invitations_controller.rb +15 -7
  78. data/app/controllers/droom/groups_controller.rb +4 -4
  79. data/app/controllers/droom/invitations_controller.rb +37 -9
  80. data/app/controllers/droom/memberships_controller.rb +5 -3
  81. data/app/controllers/droom/organisations_controller.rb +53 -0
  82. data/app/controllers/droom/people_controller.rb +46 -27
  83. data/app/controllers/droom/preferences_controller.rb +34 -0
  84. data/app/controllers/droom/scraps_controller.rb +77 -0
  85. data/app/controllers/droom/search_controller.rb +66 -0
  86. data/app/controllers/droom/suggestions_controller.rb +22 -35
  87. data/app/controllers/droom/users_controller.rb +69 -0
  88. data/app/controllers/droom/venues_controller.rb +1 -2
  89. data/app/controllers/droom/youtube_controller.rb +22 -0
  90. data/app/helpers/droom/droom_helper.rb +93 -5
  91. data/app/models/droom/agenda_category.rb +8 -1
  92. data/app/models/droom/calendar.rb +19 -0
  93. data/app/models/droom/category.rb +4 -6
  94. data/app/models/droom/document.rb +103 -64
  95. data/app/models/droom/document_attachment.rb +13 -47
  96. data/app/models/droom/dropbox_document.rb +41 -0
  97. data/app/models/droom/dropbox_token.rb +29 -0
  98. data/app/models/droom/event.rb +125 -90
  99. data/app/models/droom/folder.rb +134 -0
  100. data/app/models/droom/group.rb +68 -27
  101. data/app/models/droom/group_invitation.rb +12 -3
  102. data/app/models/droom/invitation.rb +50 -8
  103. data/app/models/droom/mailing_list_membership.rb +128 -0
  104. data/app/models/droom/membership.rb +71 -9
  105. data/app/models/droom/organisation.rb +22 -0
  106. data/app/models/droom/page.rb +3 -3
  107. data/app/models/droom/person.rb +180 -166
  108. data/app/models/droom/personal_folder.rb +31 -0
  109. data/app/models/droom/preference.rb +35 -0
  110. data/app/models/droom/recurrence_rule.rb +1 -1
  111. data/app/models/droom/scrap.rb +110 -0
  112. data/app/models/droom/tag.rb +120 -0
  113. data/app/models/droom/tagging.rb +13 -0
  114. data/app/models/droom/user.rb +211 -0
  115. data/app/models/droom/user_action_observer.rb +12 -0
  116. data/app/models/droom/venue.rb +56 -39
  117. data/app/views/cropper/uploads/_crop.html.haml +46 -0
  118. data/app/views/devise/mailer/confirmation_instructions.en.html.haml +24 -0
  119. data/app/views/devise/mailer/reset_password_instructions.en.html.haml +21 -0
  120. data/app/views/devise/passwords/edit.html.haml +31 -0
  121. data/app/views/devise/passwords/new.html.haml +21 -0
  122. data/app/views/devise/sessions/new.html.haml +33 -0
  123. data/app/views/droom/agenda_categories/_form.html.haml +22 -0
  124. data/app/views/droom/agenda_categories/new.html.haml +6 -0
  125. data/app/views/droom/calendars/_action_menu.html.haml +6 -0
  126. data/app/views/droom/calendars/index.html.haml +12 -0
  127. data/app/views/droom/calendars/show.rss.builder +0 -0
  128. data/app/views/droom/confirmations/show.html.haml +40 -0
  129. data/app/views/droom/dashboard/_calendar.html.haml +1 -0
  130. data/app/views/droom/dashboard/_folders.html.haml +5 -0
  131. data/app/views/droom/dashboard/_future_events.html.haml +18 -0
  132. data/app/views/droom/dashboard/_invitations.html.haml +1 -0
  133. data/app/views/droom/dashboard/_past_events.haml +14 -0
  134. data/app/views/droom/dashboard/_quicksearch.html.haml +6 -0
  135. data/app/views/droom/dashboard/_stream.html.haml +9 -0
  136. data/app/views/droom/dashboard/index.html.haml +5 -3
  137. data/app/views/droom/documents/_action_menu.html.haml +7 -0
  138. data/app/views/droom/documents/_documents.html.haml +5 -0
  139. data/app/views/droom/documents/_documents_list.html.haml +6 -6
  140. data/app/views/droom/documents/_documents_table.html.haml +29 -10
  141. data/app/views/droom/documents/_form.html.haml +3 -7
  142. data/app/views/droom/documents/_listing.html.haml +5 -6
  143. data/app/views/droom/documents/_pagination.html.haml +8 -0
  144. data/app/views/droom/documents/_search_result.html.haml +14 -0
  145. data/app/views/droom/documents/_suggested.html.haml +0 -5
  146. data/app/views/droom/documents/_table_document.html.haml +2 -8
  147. data/app/views/droom/documents/edit.html.haml +7 -1
  148. data/app/views/droom/documents/index.html.haml +10 -27
  149. data/app/views/droom/documents/new.html.haml +10 -1
  150. data/app/views/droom/dropbox_tokens/new.html.haml +6 -0
  151. data/app/views/droom/events/_action_menu.html.haml +15 -0
  152. data/app/views/droom/events/_event.html.haml +67 -57
  153. data/app/views/droom/events/_form.html.haml +15 -4
  154. data/app/views/droom/events/_invitations.html.haml +4 -19
  155. data/app/views/droom/events/_search_result.html.haml +19 -0
  156. data/app/views/droom/events/_views.html.haml +2 -2
  157. data/app/views/droom/events/edit.html.haml +7 -1
  158. data/app/views/droom/events/index.html.haml +27 -10
  159. data/app/views/droom/events/index.rss.builder +1 -1
  160. data/app/views/droom/events/new.html.haml +6 -1
  161. data/app/views/droom/events/show.html.haml +5 -1
  162. data/app/views/droom/folders/_action_menu.html.haml +14 -0
  163. data/app/views/droom/folders/_attachments.html.haml +3 -0
  164. data/app/views/droom/folders/_contents.html.haml +6 -0
  165. data/app/views/droom/folders/_folder.html.haml +20 -0
  166. data/app/views/droom/folders/_folders.html.haml +2 -0
  167. data/app/views/droom/folders/_form.html.haml +18 -0
  168. data/app/views/droom/folders/edit.html.haml +6 -0
  169. data/app/views/droom/folders/index.html.haml +32 -0
  170. data/app/views/droom/folders/new.html.haml +6 -0
  171. data/app/views/droom/folders/show.html.haml +1 -0
  172. data/app/views/droom/group_invitations/_form.html.haml +15 -4
  173. data/app/views/droom/group_invitations/new.html.haml +6 -1
  174. data/app/views/droom/groups/_action_menu.haml +11 -0
  175. data/app/views/droom/groups/_form.html.haml +10 -11
  176. data/app/views/droom/groups/_group.html.haml +9 -10
  177. data/app/views/droom/groups/_groups.html.haml +2 -3
  178. data/app/views/droom/groups/_search_result.html.haml +16 -0
  179. data/app/views/droom/groups/_suggested.html.haml +7 -0
  180. data/app/views/droom/groups/edit.html.haml +7 -1
  181. data/app/views/droom/groups/index.html.haml +6 -3
  182. data/app/views/droom/groups/new.html.haml +7 -0
  183. data/app/views/droom/groups/show.html.haml +1 -1
  184. data/app/views/droom/invitations/_created.html.haml +1 -1
  185. data/app/views/droom/invitations/_form.html.haml +9 -5
  186. data/app/views/droom/invitations/_invitation.html.haml +9 -0
  187. data/app/views/droom/invitations/_invitations.html.haml +8 -0
  188. data/app/views/droom/invitations/new.html.haml +6 -1
  189. data/app/views/droom/memberships/_member.html.haml +1 -1
  190. data/app/views/droom/memberships/_membership_toggle.html.haml +10 -0
  191. data/app/views/droom/memberships/new.html.haml +10 -0
  192. data/app/views/droom/organisations/_action_menu.html.haml +7 -0
  193. data/app/views/droom/organisations/_form.html.haml +25 -0
  194. data/app/views/droom/organisations/_organisation.html.haml +23 -0
  195. data/app/views/droom/organisations/_organisations.html.haml +2 -0
  196. data/app/views/droom/organisations/_suggested.html.haml +7 -0
  197. data/app/views/droom/organisations/edit.html.haml +6 -0
  198. data/app/views/droom/organisations/index.html.haml +20 -0
  199. data/app/views/droom/organisations/new.html.haml +6 -0
  200. data/app/views/droom/organisations/show.html.haml +1 -0
  201. data/app/views/droom/pages/_full_page.html.haml +1 -1
  202. data/app/views/droom/pages/index.html.haml +1 -1
  203. data/app/views/droom/panels/_account.html.haml +16 -0
  204. data/app/views/droom/panels/_admin.html.haml +23 -0
  205. data/app/views/droom/panels/_devices.html.haml +19 -0
  206. data/app/views/droom/panels/_dropbox.html.haml +17 -0
  207. data/app/views/droom/panels/_email.html.haml +16 -0
  208. data/app/views/droom/panels/_keywords.html.haml +3 -0
  209. data/app/views/droom/panels/_networks.html.haml +3 -0
  210. data/app/views/droom/panels/_readers.html.haml +18 -0
  211. data/app/views/droom/panels/_rss.html.haml +10 -0
  212. data/app/views/droom/panels/_search.html.haml +16 -0
  213. data/app/views/droom/panels/_vcal.html.haml +3 -0
  214. data/app/views/droom/people/_action_menu.html.haml +22 -0
  215. data/app/views/droom/people/_form.html.haml +69 -39
  216. data/app/views/droom/people/_listing.html.haml +19 -0
  217. data/app/views/droom/people/_memberships.html.haml +24 -0
  218. data/app/views/droom/people/_people.html.haml +5 -29
  219. data/app/views/droom/people/_person.html.haml +30 -32
  220. data/app/views/droom/people/_search_result.html.haml +14 -0
  221. data/app/views/droom/people/_suggested.html.haml +10 -5
  222. data/app/views/droom/people/edit.html.haml +9 -1
  223. data/app/views/droom/people/index.html.haml +6 -9
  224. data/app/views/droom/people/new.html.haml +6 -1
  225. data/app/views/droom/people/show.html.haml +1 -1
  226. data/app/views/droom/preferences/_checkbox.html.haml +7 -0
  227. data/app/views/droom/preferences/_radio_set.html.haml +9 -0
  228. data/app/views/droom/scraps/_action_menu.html.haml +9 -0
  229. data/app/views/droom/scraps/_caption.html.haml +9 -0
  230. data/app/views/droom/scraps/_credit.html.haml +10 -0
  231. data/app/views/droom/scraps/_form.html.haml +77 -0
  232. data/app/views/droom/scraps/_heading.html.haml +16 -0
  233. data/app/views/droom/scraps/_scrap.html.haml +17 -0
  234. data/app/views/droom/scraps/_search_result.html.haml +5 -0
  235. data/app/views/droom/scraps/_stream.html.haml +4 -0
  236. data/app/views/droom/scraps/_suggested.html.haml +5 -0
  237. data/app/views/droom/scraps/_thumb.html.haml +5 -0
  238. data/app/views/droom/scraps/edit.html.haml +2 -0
  239. data/app/views/droom/scraps/full/_document.html.haml +6 -0
  240. data/app/views/droom/scraps/full/_event.html.haml +20 -0
  241. data/app/views/droom/scraps/full/_image.html.haml +4 -0
  242. data/app/views/droom/scraps/full/_link.html.haml +5 -0
  243. data/app/views/droom/scraps/full/_quote.html.haml +8 -0
  244. data/app/views/droom/scraps/full/_text.html.haml +4 -0
  245. data/app/views/droom/scraps/full/_video.html.haml +4 -0
  246. data/app/views/droom/scraps/index.atom.builder +26 -0
  247. data/app/views/droom/scraps/index.html.haml +15 -0
  248. data/app/views/droom/scraps/new.html.haml +2 -0
  249. data/app/views/droom/scraps/show.html.haml +4 -0
  250. data/app/views/droom/scraps/thumbs/_document.html.haml +9 -0
  251. data/app/views/droom/scraps/thumbs/_event.html.haml +17 -0
  252. data/app/views/droom/scraps/thumbs/_image.html.haml +6 -0
  253. data/app/views/droom/scraps/thumbs/_link.html.haml +10 -0
  254. data/app/views/droom/scraps/thumbs/_quote.html.haml +8 -0
  255. data/app/views/droom/scraps/thumbs/_text.html.haml +8 -0
  256. data/app/views/droom/scraps/thumbs/_video.html.haml +6 -0
  257. data/app/views/droom/shared/_controls.html.haml +5 -3
  258. data/app/views/droom/shared/_excerpt.html.haml +2 -0
  259. data/app/views/droom/shared/_navigation.html.haml +4 -4
  260. data/app/views/droom/shared/_panels.html.haml +4 -0
  261. data/app/views/droom/shared/_quicklinks.html.haml +5 -0
  262. data/app/views/droom/shared/_search_form.html.haml +2 -1
  263. data/app/views/droom/shared/_search_results.html.haml +9 -0
  264. data/app/views/droom/shared/_suggestions.html.haml +13 -9
  265. data/app/views/droom/shared/_title_excerpt.haml +2 -0
  266. data/app/views/droom/shared/search.html.haml +18 -0
  267. data/app/views/droom/users/_confirmation.html.haml +2 -0
  268. data/app/views/droom/users/_dropbox_status.html.haml +2 -0
  269. data/app/views/droom/users/_form.html.haml +34 -0
  270. data/app/views/droom/users/_user.html.haml +2 -0
  271. data/app/views/droom/users/_user_or_person.html.haml +63 -0
  272. data/app/views/droom/users/_users_table.html.haml +17 -0
  273. data/app/views/droom/users/edit.html.haml +10 -0
  274. data/app/views/droom/users/index.html.haml +42 -0
  275. data/app/views/droom/users/unwelcome.en.html.haml +17 -0
  276. data/app/views/droom/venues/_search_result.html.haml +17 -0
  277. data/app/views/droom/youtube/show.html.haml +12 -0
  278. data/app/views/kaminari/_paginator.html.haml +16 -0
  279. data/app/views/layouts/droom/application.html.haml +17 -17
  280. data/app/views/layouts/droom/email.html.haml +59 -0
  281. data/config/cucumber.yml +8 -0
  282. data/config/initializers/devise.rb +240 -0
  283. data/config/locales/devise.en.yml +58 -0
  284. data/config/locales/en.yml +203 -32
  285. data/config/routes.rb +55 -16
  286. data/config/sunspot.yml +17 -0
  287. data/db/migrate/20121120115447_tags.rb +18 -0
  288. data/db/migrate/20130116155331_dropbox_tokens.rb +9 -0
  289. data/db/migrate/20130118103540_folders.rb +47 -0
  290. data/db/migrate/20130124113715_preferences.rb +10 -0
  291. data/db/migrate/20130125132427_users_in_droom.rb +58 -0
  292. data/db/migrate/20130129142307_mobile_phones.rb +7 -0
  293. data/db/migrate/20130130120124_folder_ancestry_to_parents.rb +7 -0
  294. data/db/migrate/20130131161430_mailing_lists.rb +37 -0
  295. data/db/migrate/20130207091903_preference_uuids.rb +5 -0
  296. data/db/migrate/20130207123614_stream.rb +13 -0
  297. data/db/migrate/20130208035113_access_token_secret.rb +5 -0
  298. data/db/migrate/20130214145014_person_image.rb +9 -0
  299. data/db/migrate/20130217152644_devise_confirmable.rb +13 -0
  300. data/db/migrate/20130225095328_create_droom_calendars.rb +20 -0
  301. data/db/migrate/20130226092944_give_scraps_document.rb +5 -0
  302. data/db/migrate/20130228083509_privateness.rb +9 -0
  303. data/db/migrate/20130228134143_store_metadata.rb +5 -0
  304. data/db/migrate/20130305150648_folders_nicely.rb +6 -0
  305. data/db/migrate/20130305151936_niceties.rb +7 -0
  306. data/db/migrate/20130308103807_create_droom_dropbox_documents.rb +11 -0
  307. data/db/migrate/20130308154552_dropbox_documents_changed.rb +5 -0
  308. data/db/migrate/20130326135738_user_titles.rb +5 -0
  309. data/lib/droom.rb +189 -22
  310. data/lib/droom/engine.rb +6 -1
  311. data/lib/droom/folders.rb +106 -0
  312. data/lib/droom/lazy_hash.rb +73 -0
  313. data/lib/droom/{helpers.rb → model_helpers.rb} +1 -1
  314. data/lib/droom/monkeys.rb +21 -2
  315. data/lib/droom/routing.rb +13 -0
  316. data/lib/droom/searchability.rb +25 -0
  317. data/lib/droom/taggability.rb +60 -0
  318. data/lib/droom/title_case.rb +101 -0
  319. data/lib/droom/user_config.rb +67 -0
  320. data/lib/droom/validators.rb +6 -0
  321. data/lib/droom/version.rb +1 -1
  322. data/lib/generators/droom/install/templates/droom_initializer.rb +0 -1
  323. data/lib/tasks/cucumber.rake +65 -0
  324. data/spec/datasets/calendar_events_dataset.rb +44 -0
  325. data/spec/datasets/calendar_pages_dataset.rb +8 -0
  326. data/spec/datasets/calendar_sites_dataset.rb +6 -0
  327. data/spec/datasets/calendars_dataset.rb +34 -0
  328. data/spec/datasets/documents_dataset.rb +28 -0
  329. data/spec/datasets/recurrence_dataset.rb +7 -0
  330. data/spec/dummy/README.rdoc +261 -0
  331. data/spec/dummy/Rakefile +7 -0
  332. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  333. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  334. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  335. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  336. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  337. data/spec/dummy/config.ru +4 -0
  338. data/spec/dummy/config/application.rb +65 -0
  339. data/spec/dummy/config/boot.rb +10 -0
  340. data/spec/dummy/config/database.yml +21 -0
  341. data/spec/dummy/config/environment.rb +5 -0
  342. data/spec/dummy/config/environments/development.rb +38 -0
  343. data/spec/dummy/config/environments/production.rb +67 -0
  344. data/spec/dummy/config/environments/test.rb +38 -0
  345. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  346. data/spec/dummy/config/initializers/inflections.rb +15 -0
  347. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  348. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  349. data/spec/dummy/config/initializers/session_store.rb +8 -0
  350. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  351. data/spec/dummy/config/locales/en.yml +7 -0
  352. data/spec/dummy/config/routes.rb +3 -0
  353. data/spec/dummy/config/sunspot.yml +17 -0
  354. data/spec/dummy/db/migrate/20120911070124_create_droom_data.droom.rb +135 -0
  355. data/spec/dummy/db/migrate/20120921094604_agenda_sections.droom.rb +14 -0
  356. data/spec/dummy/db/migrate/20120921094605_add_postal_address_to_people.droom.rb +11 -0
  357. data/spec/dummy/db/migrate/20121102064845_give_groups_descriptions.droom.rb +6 -0
  358. data/spec/dummy/db/migrate/20121102064846_more_names.droom.rb +6 -0
  359. data/spec/dummy/db/migrate/20121102064847_event_agenda_sections.droom.rb +14 -0
  360. data/spec/dummy/db/migrate/20121102064848_create_group_invitations.droom.rb +11 -0
  361. data/spec/dummy/db/migrate/20121102064849_give_people_positions.droom.rb +6 -0
  362. data/spec/dummy/db/migrate/20121102064850_help_pages.droom.rb +14 -0
  363. data/spec/dummy/db/migrate/20121102064851_category_slugs.droom.rb +6 -0
  364. data/spec/dummy/db/migrate/20121102064852_document_links.droom.rb +15 -0
  365. data/spec/dummy/db/migrate/20121102064853_people_visibility.droom.rb +8 -0
  366. data/spec/dummy/db/migrate/20121102094820_shy_people.droom.rb +6 -0
  367. data/spec/dummy/db/migrate/20121102095927_visibility_defaults.droom.rb +10 -0
  368. data/spec/dummy/db/migrate/20130121122352_tags.droom.rb +19 -0
  369. data/spec/dummy/db/migrate/20130121122353_dropbox.droom.rb +10 -0
  370. data/spec/dummy/db/migrate/20130121122354_folders.droom.rb +48 -0
  371. data/spec/dummy/db/migrate/20130128142902_memberships_expire.droom.rb +6 -0
  372. data/spec/dummy/db/migrate/20130128142903_give_documents_extracted_text.droom.rb +6 -0
  373. data/spec/dummy/db/migrate/20130128142904_preferences.droom.rb +11 -0
  374. data/spec/dummy/db/migrate/20130128142905_users_in_droom.droom.rb +59 -0
  375. data/spec/dummy/db/migrate/20130130120631_folder_ancestry_to_parents.droom.rb +8 -0
  376. data/spec/dummy/db/migrate/20130201103737_mobile_phones.droom.rb +8 -0
  377. data/spec/dummy/db/migrate/20130201103738_mailing_lists.droom.rb +38 -0
  378. data/spec/dummy/db/schema.rb +327 -0
  379. data/spec/dummy/log/sunspot-solr-test.log.1 +222 -0
  380. data/spec/dummy/public/404.html +26 -0
  381. data/spec/dummy/public/422.html +26 -0
  382. data/spec/dummy/public/500.html +25 -0
  383. data/spec/dummy/public/favicon.ico +0 -0
  384. data/spec/dummy/public/system/droom/documents/files/000/000/001/original/frog.png +0 -0
  385. data/spec/dummy/public/system/droom/documents/files/000/000/001/original/rat.png +0 -0
  386. data/spec/dummy/script/rails +6 -0
  387. data/spec/dummy/solr/conf/admin-extra.html +31 -0
  388. data/spec/dummy/solr/conf/elevate.xml +36 -0
  389. data/spec/dummy/solr/conf/mapping-ISOLatin1Accent.txt +246 -0
  390. data/spec/dummy/solr/conf/protwords.txt +21 -0
  391. data/spec/dummy/solr/conf/schema.xml +238 -0
  392. data/spec/dummy/solr/conf/scripts.conf +24 -0
  393. data/spec/dummy/solr/conf/solrconfig.xml +934 -0
  394. data/spec/dummy/solr/conf/spellings.txt +2 -0
  395. data/spec/dummy/solr/conf/stopwords.txt +58 -0
  396. data/spec/dummy/solr/conf/synonyms.txt +31 -0
  397. data/spec/dummy/solr/data/development/index/segments.gen +0 -0
  398. data/spec/dummy/solr/data/development/index/segments_1 +0 -0
  399. data/spec/dummy/solr/data/development/spellchecker/segments.gen +0 -0
  400. data/spec/dummy/solr/data/development/spellchecker/segments_1 +0 -0
  401. data/spec/dummy/solr/data/test/index/segments.gen +0 -0
  402. data/spec/dummy/solr/data/test/index/segments_3nu +0 -0
  403. data/spec/dummy/solr/data/test/spellchecker/segments.gen +0 -0
  404. data/spec/dummy/solr/data/test/spellchecker/segments_1 +0 -0
  405. data/spec/dummy/webdav/1/group/rat.png +0 -0
  406. data/spec/dummy/webdav/1/unattached/rat.png +0 -0
  407. data/spec/dummy/webdav/group/rat.png +0 -0
  408. data/spec/dummy/webdav/unattached/rat.png +0 -0
  409. data/spec/dummy/webdav/unattached/rat_v1.png +0 -0
  410. data/spec/factories/agenda_categories.rb +5 -0
  411. data/spec/factories/categories.rb +5 -0
  412. data/spec/factories/documents.rb +16 -0
  413. data/spec/factories/events.rb +41 -0
  414. data/spec/factories/folders.rb +5 -0
  415. data/spec/factories/groups.rb +6 -0
  416. data/spec/factories/memberships.rb +5 -0
  417. data/spec/factories/people.rb +16 -0
  418. data/spec/factories/recurrence_rules.rb +25 -0
  419. data/spec/factories/user.rb +6 -0
  420. data/spec/fixtures/dummy.ics +59 -0
  421. data/spec/fixtures/images/frog.png +0 -0
  422. data/spec/fixtures/images/rat.png +0 -0
  423. data/spec/fixtures/ny.ics +36 -0
  424. data/spec/lib/droom/folders_spec.rb +46 -0
  425. data/spec/lib/droom/lazy_hash_spec.rb +33 -0
  426. data/spec/models/droom/agenda_category_spec.rb +15 -0
  427. data/spec/models/droom/document_spec.rb +76 -0
  428. data/spec/models/droom/event_spec.rb +154 -0
  429. data/spec/models/droom/folder_spec.rb +5 -0
  430. data/spec/models/droom/ical_spec.rb +62 -0
  431. data/spec/models/droom/mailing_list_membership_spec.rb +81 -0
  432. data/spec/models/droom/membership_spec.rb +22 -0
  433. data/spec/models/droom/person_spec.rb +72 -0
  434. data/spec/models/droom/recurrence_rule_spec.rb +81 -0
  435. data/spec/models/droom/user_spec.rb +27 -0
  436. data/spec/models/droom/visibility_spec.rb +6 -0
  437. data/spec/spec_helper.rb +119 -0
  438. data/spec/support/matchers/content_type_matcher.rb +17 -0
  439. metadata +591 -36
  440. data/app/assets/javascripts/droom/calendar.js.coffee +0 -121
  441. data/app/assets/javascripts/droom/drag_sort.js.coffee +0 -22
  442. data/app/assets/javascripts/droom/forms.js.coffee +0 -746
  443. data/app/assets/javascripts/droom/sort.js.coffee +0 -126
  444. data/app/assets/javascripts/droom/suggester.js.coffee +0 -230
  445. data/app/controllers/droom/document_attachments_controller.rb +0 -19
  446. data/app/models/droom/document_link.rb +0 -31
  447. data/app/models/droom/personal_document.rb +0 -98
  448. data/app/views/droom/dashboard/_marginalia.html.haml +0 -3
  449. data/app/views/droom/dashboard/_my_future_events.html.haml +0 -9
  450. data/app/views/droom/dashboard/_my_group_documents.html.haml +0 -6
  451. data/app/views/droom/dashboard/_my_past_events.haml +0 -6
  452. data/app/views/droom/documents/_event_document_form.html.haml +0 -15
  453. data/app/views/droom/errors/bang.html.haml +0 -12
  454. data/app/views/droom/errors/not_allowed.html.haml +0 -12
  455. data/app/views/droom/errors/not_found.html.haml +0 -12
  456. data/app/views/droom/events/_attachment.html.haml +0 -1
  457. data/app/views/droom/events/_attachment_list.html.haml +0 -4
  458. data/app/views/droom/invitations/_attending_people.html.haml +0 -8
  459. data/config/initializers/dav.rb +0 -2
@@ -0,0 +1,31 @@
1
+ module Droom
2
+ class PersonalFolder < ActiveRecord::Base
3
+ belongs_to :person
4
+ belongs_to :folder
5
+
6
+ def copy_to_dropbox
7
+
8
+ end
9
+
10
+ def copy_to_dav
11
+
12
+ end
13
+
14
+ #todo: lifted from Person and awaiting translation
15
+ #
16
+ # def create_and_update_dav_directories
17
+ # document_links.each do |dl|
18
+ # p "-> creating DAV directory #{dl.slug}"
19
+ # create_dav_directory(dl.slug)
20
+ # end
21
+ # end
22
+ #
23
+ # def create_dav_directory(name)
24
+ # FileUtils.mkdir_p(Rails.root + "#{Droom.dav_root}/#{self.id}/#{name}")
25
+ # end
26
+ #
27
+
28
+ # association helpers give us more readable logic elsewhere.
29
+
30
+ end
31
+ end
@@ -0,0 +1,35 @@
1
+ # Preferences...
2
+
3
+ module Droom
4
+ class Preference < ActiveRecord::Base
5
+ attr_accessible :key, :value, :uuid
6
+ belongs_to :created_by, :class_name => "Droom::User"
7
+ validates :key, :presence => true, :uniqueness => true
8
+
9
+ def set(value)
10
+ if boolean?
11
+ self.value = value ? 1 : 0
12
+ else
13
+ self.value = value
14
+ end
15
+ self.save if changed?
16
+ end
17
+
18
+ def get
19
+ if boolean?
20
+ value.to_i == 1
21
+ else
22
+ value
23
+ end
24
+ end
25
+
26
+ def boolean?
27
+ key.last == "?"
28
+ end
29
+
30
+ def uuid
31
+ self[:uuid] ||= SecureRandom.uuid
32
+ end
33
+
34
+ end
35
+ end
@@ -1,7 +1,7 @@
1
1
  module Droom
2
2
  class RecurrenceRule < ActiveRecord::Base
3
3
 
4
- belongs_to :created_by, :class_name => 'User'
4
+ belongs_to :created_by, :class_name => "Droom::User"
5
5
  belongs_to :event
6
6
 
7
7
  attr_accessible :period, :interval, :basis, :limiting_count, :limiting_date
@@ -0,0 +1,110 @@
1
+ module Droom
2
+ class Scrap < ActiveRecord::Base
3
+ belongs_to :created_by, :class_name => "Droom::User"
4
+ belongs_to :event, :class_name => "Droom::Event"
5
+ accepts_nested_attributes_for :event
6
+
7
+ belongs_to :document, :class_name => "Droom::Document", :dependent => :destroy
8
+ accepts_nested_attributes_for :document
9
+
10
+ has_upload :image,
11
+ :geometry => "580x326#",
12
+ :styles => {
13
+ :icon => "32x18#",
14
+ :thumb => "160x90#",
15
+ :precrop => "1200x1200^"
16
+ }
17
+
18
+ searchable do
19
+ text :name, :boost => 10, :stored => true
20
+ text :body, :stored => true
21
+ text :note
22
+ end
23
+
24
+ def self.highlight_fields
25
+ [:name, :body]
26
+ end
27
+
28
+ attr_accessible :name, :body, :image, :description, :scraptype, :note, :created_by, :event, :event_attributes, :document, :document_attributes
29
+ before_save :get_youtube_thumbnail
30
+
31
+ scope :by_date, order("droom_scraps.created_at DESC")
32
+
33
+ scope :later_than, lambda { |scrap|
34
+ where(["created_at > ?", scrap.created_at]).order("droom_scraps.created_at ASC")
35
+ }
36
+
37
+ scope :earlier_than, lambda { |scrap|
38
+ where(["created_at < ?", scrap.created_at]).order("droom_scraps.created_at DESC")
39
+ }
40
+
41
+ scope :matching, lambda { |fragment|
42
+ fragment = "%#{fragment}%"
43
+ where('droom_scraps.name LIKE :f OR droom_scraps.body LIKE :f OR droom_scraps.note LIKE :f', :f => fragment)
44
+ }
45
+
46
+ scope :visible_to, lambda { |person|
47
+ where("1=1")
48
+ }
49
+
50
+ Droom.scrap_types.each do |t|
51
+ define_method(:"#{t}?") { scraptype == t.to_s }
52
+ scope t.pluralize.to_sym, where(["scraptype == ?", t])
53
+ end
54
+
55
+ def wordiness
56
+ if body.length < 48
57
+ 'word'
58
+ elsif body.length < 320
59
+ 'phrase'
60
+ elsif body.length < 800
61
+ 'paragraph'
62
+ else
63
+ 'text'
64
+ end
65
+ end
66
+
67
+ def text_size
68
+ if l = body.length
69
+ ((560.0/(1.4 * l+150.0)) + 0.25) / 1.5
70
+ else
71
+ 1
72
+ end
73
+ end
74
+
75
+ def url_with_protocol
76
+ body =~ /^https?:\/\// ? body : "http://#{body}"
77
+ end
78
+
79
+ def url_without_protocol
80
+ body.sub(/^https?:\/\//, '')
81
+ end
82
+
83
+ def as_search_result
84
+ {
85
+ :type => 'scrap',
86
+ :prompt => name,
87
+ :value => name,
88
+ :id => id
89
+ }
90
+ end
91
+
92
+ def next_younger
93
+ Droom::Scrap.later_than(self).first
94
+ end
95
+
96
+ def next_older
97
+ Droom::Scrap.earlier_than(self).first
98
+ end
99
+
100
+ protected
101
+
102
+ def get_youtube_thumbnail
103
+ # youtube id is held in the 'note' column.
104
+ if scraptype == "video" && body?
105
+ self.image = URI.parse("http://img.youtube.com/vi/#{body}/0.jpg")
106
+ end
107
+ end
108
+
109
+ end
110
+ end
@@ -0,0 +1,120 @@
1
+ # Tags are simple one-word descriptors. There is no hierarchy or other structure among them.
2
+ # They are strictly catalogue data, used to locate people but not treated as part of the person record.
3
+
4
+ module Droom
5
+ class Tag < ActiveRecord::Base
6
+ # They are attached to people through many-to-many taggings.
7
+ #
8
+ has_many :taggings
9
+ has_many :taggees, :through => :taggings
10
+ before_save :downcase
11
+
12
+ ## Suggestions
13
+ #
14
+ # There is a tag-suggesting mechanism in the front end to encourage tag reuse and consistency.
15
+ # It rests on this simple scope, which returns all tags matching a given string fragment.
16
+ #
17
+ scope :matching, lambda { |fragment|
18
+ fragment = "%#{fragment}%"
19
+ where('tags.name like ?', fragment)
20
+ }
21
+
22
+ # The public-facing search engine is faceted and relies on a similar but broader suggestion mechanism
23
+ # that offers both tags and institutions. In that situation we only want to display tags that will give
24
+ # give results, so we limit the suggestions to only those tags that have been applied to a person.
25
+ #
26
+ scope :in_use,
27
+ joins("INNER JOIN taggings ON taggings.tag_id = tags.id")
28
+ .group('tags.id')
29
+ .having('count(taggings.tag_id) > 0')
30
+
31
+ # This returns a list of all the tags attached to any of a given set of objects.
32
+ # In future it will support cloud-weighting.
33
+ #
34
+ scope :attached_to_any_of, lambda {|these|
35
+ these = [these].flatten
36
+ type = these.first.class.to_s
37
+ placeholders = these.map{"?"}.join(',')
38
+ select("droom_tags.*, count(droom_taggings.id) as use_count")
39
+ .joins("INNER JOIN droom_taggings ON droom_taggings.tag_id = droom_tags.id")
40
+ .where(["droom_taggings.taggee_type = ? and droom_taggings.taggee_id IN (#{placeholders})", *these.map(&:id).unshift(type)])
41
+ .group('droom_tags.id')
42
+ }
43
+
44
+ # Suggestions are returned in a minimal format and need only contain name and (for the public search
45
+ # where there are more possibilities) the type of suggestion.
46
+ #
47
+ def as_json(options={})
48
+ {
49
+ :id => id,
50
+ :name => name,
51
+ :type => 'tag'
52
+ }
53
+ end
54
+
55
+ ## Keyword lists
56
+ #
57
+ # Sometimes we want the interface to present a simple comma-separated list.
58
+ # These methods help to move to and from that form.
59
+ #
60
+ def self.from_list(list=[], or_create=true)
61
+ list = list.split(/[,;]\s*/) if String === list
62
+ list.uniq.map{|t| self.for(t, or_create) }.compact if list && list.any?
63
+ end
64
+
65
+ # Renders a set of tags as a comma-separated list.
66
+ #
67
+ def self.to_list(tags=[])
68
+ tags.uniq.map(&:name).join(', ')
69
+ end
70
+
71
+ # Finds or creates a tag with the supplied title
72
+ #
73
+ def self.for(name, or_create=true)
74
+ if or_create
75
+ find_or_create_by_name(name)
76
+ else
77
+ find_by_name(name)
78
+ end
79
+ end
80
+
81
+
82
+ ## Clouds
83
+ #
84
+ # The administrative interface offers a big tag cloud and drag and drop tag-merging. Tag size in the
85
+ # cloud is based on a usage count that is retrieved here in a join with the taggings table. The cloud
86
+ # display logic can be found in the [application_helper](../controllers/application_helper.html).
87
+ #
88
+ attr_accessor :cloud_size
89
+ scope :with_usage_count, lambda { |limit|
90
+ select("tags.*, count(tt.id) AS weight").joins("INNER JOIN taggings as tt ON tt.tag_id = tags.id").group("tt.tag_id").order("weight DESC").limit(limit)
91
+ }
92
+
93
+ # *self.for_cloud* uses that scope to return a list of the most popular tags, weighted for display as a tag cloud
94
+ # and re-sorted into alphabetical order (since to select the most popular we originally had to sort by weighting).
95
+ #
96
+ def self.for_cloud(limit=100)
97
+ with_usage_count(limit).sort_by(&:name)
98
+ end
99
+
100
+ # This is here just to make tag interpolation a bit more readable.
101
+ #
102
+ def to_s
103
+ name
104
+ end
105
+
106
+ ## Admin
107
+ #
108
+ def assimilate(tag)
109
+ self.taggees << tag.taggees
110
+ tag.destroy
111
+ end
112
+
113
+ protected
114
+
115
+ def downcase
116
+ self.name = self.name.downcase
117
+ end
118
+
119
+ end
120
+ end
@@ -0,0 +1,13 @@
1
+ # Taggings are the many to many links that associated tags with people. There isn't much to see here.
2
+
3
+ module Droom
4
+ class Tagging < ActiveRecord::Base
5
+ belongs_to :tag
6
+ belongs_to :taggee, :polymorphic => true
7
+
8
+ # The tagging interface allows the creation of new tags on save but in normal use this would never be hit:
9
+ # the ajax-based tag-adder creates tags in the background so the form needs only the nested tagging fields.
10
+ #
11
+ accepts_nested_attributes_for :tag, :reject_if => :all_blank
12
+ end
13
+ end
@@ -0,0 +1,211 @@
1
+ module Droom
2
+ class User < ActiveRecord::Base
3
+
4
+ attr_accessible :name, :forename, :email, :password, :password_confirmation, :admin, :newly_activated, :update_person_email, :preferences_attributes, :confirm, :old_id, :remove_person
5
+ has_one :person
6
+ has_many :dropbox_tokens, :foreign_key => "created_by_id"
7
+ has_many :preferences, :foreign_key => "created_by_id"
8
+ accepts_nested_attributes_for :preferences, :allow_destroy => true
9
+
10
+ receives_messages# :groups => [:unconfirmed, :personed, :administrative]
11
+
12
+ devise :database_authenticatable,
13
+ :encryptable,
14
+ :recoverable,
15
+ :rememberable,
16
+ :trackable,
17
+ :confirmable,
18
+ :token_authenticatable,
19
+ :encryptor => :sha512
20
+
21
+ before_create :ensure_authentication_token
22
+
23
+ attr_accessor :newly_activated, :update_person_email, :confirm, :remove_person
24
+
25
+ # validates :password, :length => { :minimum => 6 }, :if => :password_required?
26
+
27
+ scope :unconfirmed, where("confirmed_at IS NULL")
28
+ scope :administrative, where(:admin => true)
29
+
30
+ scope :personed, select("droom_users.*")
31
+ .joins("INNER JOIN droom_people as dp ON dp.user_id = droom_users.id")
32
+
33
+ scope :unpersoned, select("droom_users.*")
34
+ .joins("LEFT OUTER JOIN droom_people as dp ON dp.user_id = droom_users.id")
35
+ .having("count(dp.id) = 0")
36
+
37
+ scope :with_person_in_group, lambda { |group|
38
+ group = group.id if group.is_a? Droom::Group
39
+ select("droom_users.*")
40
+ .joins("INNER JOIN droom_people as dp ON dp.user_id = droom_users.id")
41
+ .joins("INNER JOIN droom_memberships as dm ON dp.id = dm.person_id")
42
+ .where("dm.group_id" => group)
43
+ }
44
+
45
+ # Messaging groups are normally scopes passed through when receives_messages is called,
46
+ # but anything will work that can be called on the class and return a set of instances.
47
+ # Here we're overriding the getter so as to offer sending by group membership as well as
48
+ # the usual scoping.
49
+ #
50
+ def self.messaging_groups
51
+ unless @messaging_groups
52
+ @messaging_groups = {
53
+ :unconfirmed => lambda { Droom::User.unconfirmed},
54
+ :personed => lambda { Droom::User.personed },
55
+ :administrative => lambda { Droom::User.administrative }
56
+ }
57
+ Droom::Group.all.each do |group|
58
+ @messaging_groups[group.slug.to_sym] = lambda { Droom::User.with_person_in_group(group.id) }
59
+ end
60
+ end
61
+ @messaging_groups
62
+ end
63
+
64
+ def confirm=(confirmed)
65
+ confirm! if confirmed
66
+ end
67
+
68
+ def remove_person=(boolean)
69
+ if boolean
70
+ p = Droom::Person.find(person.id)
71
+ p.user = nil
72
+ p.save!
73
+ end
74
+ end
75
+
76
+ # Password is not required on creation, contrary to the devise defaults.
77
+ def password_required?
78
+ confirmed? && (!password.blank?)
79
+ end
80
+
81
+ def password_match?
82
+ Rails.logger.warn ">>> password_match? '#{password}' == '#{password_confirmation}'"
83
+ self.errors[:password] << "can't be blank" if password.blank?
84
+ self.errors[:password_confirmation] << "can't be blank" if password_confirmation.blank?
85
+ self.errors[:password_confirmation] << "does not match password" if password != password_confirmation
86
+ password == password_confirmation && !password.blank?
87
+ end
88
+
89
+ def is_person?(person)
90
+ person == self.person
91
+ end
92
+
93
+ def organisation
94
+ person.organisation if person
95
+ end
96
+
97
+ # Current user is pushed into here to make it available in models
98
+ # such as the UserActionObserver that sets ownership before save.
99
+ #
100
+ def self.current
101
+ Thread.current[:user]
102
+ end
103
+ def self.current=(user)
104
+ Thread.current[:user] = user
105
+ end
106
+
107
+ # Personal DAV repository is accessed via a DAV4rack endpoint but we have to take care of its creation and population.
108
+ #
109
+ def dav_root
110
+ dav_path = Rails.root + "webdav/#{id}"
111
+ Dir.mkdir(dav_path, 0600) unless File.exist?(dav_path)
112
+ dav_path
113
+ end
114
+
115
+ def full_name
116
+ [forename, name].compact.join(' ').strip
117
+ end
118
+
119
+ def formal_name
120
+ [title, forename, name].compact.join(' ').strip
121
+ end
122
+
123
+ def informal_name
124
+ if Droom.use_forenames
125
+ forename
126
+ else
127
+ name
128
+ end
129
+ end
130
+
131
+ def dropbox_token
132
+ unless @dropbox_token
133
+ @dropbox_token = dropbox_tokens.by_date.last || 'nope'
134
+ end
135
+ @dropbox_token unless @dropbox_token == 'nope'
136
+ end
137
+
138
+ def dropbox_client
139
+ dropbox_token.dropbox_client if dropbox_token
140
+ end
141
+
142
+ def privileged?
143
+ admin? || person && person.privileged?
144
+ end
145
+
146
+
147
+ ## Preferences
148
+ #
149
+ # User settings are held as an association with Preference objects, which are simple key:value pairs.
150
+ # The keys are usually colon:separated for namespacing purposes, eg:
151
+ #
152
+ # current_user.pref("email:enabled?")
153
+ # current_user.pref("dropbox:enabled?")
154
+ #
155
+ # Default settings are defined in Droom.user_defaults and can be defined in an initializer if the default droom
156
+ # defaults are not right for your application.
157
+ #
158
+ # `User#pref(key)` returns the **value** of the preference (whether set or default) for the given key. It is intended
159
+ # for use in views:
160
+ #
161
+ # - if current_user.pref("dropbox:enabled?")
162
+ # = link_to "copy to dropbox", dropbox_folder_url(folder)
163
+ #
164
+ def pref(key)
165
+ if pref = preferences.find_by_key(key)
166
+ pref.value
167
+ else
168
+ Droom.user_default(key)
169
+ end
170
+ end
171
+
172
+ # `User#preference(key)` always returns a preference object and is used to build control panels. If no preference
173
+ # is saved for the given key, we return a new (unsaved) one with that key and the default value.
174
+ #
175
+ def preference(key)
176
+ pref = preferences.find_or_initialize_by_key(key)
177
+ pref.value = Droom.user_default(key) unless pref.persisted?
178
+ pref
179
+ end
180
+
181
+ # Setting preferences is normally handled either by the PreferencesController or by nesting preferences
182
+ # in a user form. `User#set_pref` is a convenient console method but not otherwise used much.
183
+ #
184
+ # Preferences are set in a simple key:value way, where key usually includes some namespacing prefixes:
185
+ #
186
+ # user.set_pref("email:enabled", true)
187
+ #
188
+ def set_pref(key, value)
189
+ preferences.find_or_create_by_key(key).set(value)
190
+ end
191
+
192
+ ## Email
193
+ #
194
+ # If using `msg`, this defines the variables available in message templates.
195
+ #
196
+ def for_email
197
+ {
198
+ :informal_name => informal_name,
199
+ :formal_name => formal_name,
200
+ :forename => forename,
201
+ :name => name,
202
+ :email => email,
203
+ :confirmation_url => Droom::Engine.routes.url_helpers.new_user_confirmation_url(self, :confirmation_token => self.confirmation_token, :host => ActionMailer::Base.default_url_options[:host]),
204
+ :sign_in_url => Droom::Engine.routes.url_helpers.new_user_session_path(:host => ActionMailer::Base.default_url_options[:host]),
205
+ :password_reset_url => Droom::Engine.routes.url_helpers.new_user_password_path(self, :host => ActionMailer::Base.default_url_options[:host])
206
+ }
207
+ end
208
+
209
+
210
+ end
211
+ end