dm_core 4.2.1.5

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 (522) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +22 -0
  3. data/README.md +25 -0
  4. data/Rakefile +34 -0
  5. data/app/assets/images/dm_core/draft_menu_bg.png +0 -0
  6. data/app/assets/images/dm_core/expand.png +0 -0
  7. data/app/assets/images/dm_core/flags/ad.gif +0 -0
  8. data/app/assets/images/dm_core/flags/ae.gif +0 -0
  9. data/app/assets/images/dm_core/flags/af.gif +0 -0
  10. data/app/assets/images/dm_core/flags/ag.gif +0 -0
  11. data/app/assets/images/dm_core/flags/ai.gif +0 -0
  12. data/app/assets/images/dm_core/flags/al.gif +0 -0
  13. data/app/assets/images/dm_core/flags/am.gif +0 -0
  14. data/app/assets/images/dm_core/flags/an.gif +0 -0
  15. data/app/assets/images/dm_core/flags/ao.gif +0 -0
  16. data/app/assets/images/dm_core/flags/ar.gif +0 -0
  17. data/app/assets/images/dm_core/flags/as.gif +0 -0
  18. data/app/assets/images/dm_core/flags/at.gif +0 -0
  19. data/app/assets/images/dm_core/flags/au.gif +0 -0
  20. data/app/assets/images/dm_core/flags/aw.gif +0 -0
  21. data/app/assets/images/dm_core/flags/ax.gif +0 -0
  22. data/app/assets/images/dm_core/flags/az.gif +0 -0
  23. data/app/assets/images/dm_core/flags/ba.gif +0 -0
  24. data/app/assets/images/dm_core/flags/bb.gif +0 -0
  25. data/app/assets/images/dm_core/flags/bd.gif +0 -0
  26. data/app/assets/images/dm_core/flags/be.gif +0 -0
  27. data/app/assets/images/dm_core/flags/bf.gif +0 -0
  28. data/app/assets/images/dm_core/flags/bg.gif +0 -0
  29. data/app/assets/images/dm_core/flags/bh.gif +0 -0
  30. data/app/assets/images/dm_core/flags/bi.gif +0 -0
  31. data/app/assets/images/dm_core/flags/bj.gif +0 -0
  32. data/app/assets/images/dm_core/flags/bm.gif +0 -0
  33. data/app/assets/images/dm_core/flags/bn.gif +0 -0
  34. data/app/assets/images/dm_core/flags/bo.gif +0 -0
  35. data/app/assets/images/dm_core/flags/br.gif +0 -0
  36. data/app/assets/images/dm_core/flags/bs.gif +0 -0
  37. data/app/assets/images/dm_core/flags/bt.gif +0 -0
  38. data/app/assets/images/dm_core/flags/bv.gif +0 -0
  39. data/app/assets/images/dm_core/flags/bw.gif +0 -0
  40. data/app/assets/images/dm_core/flags/by.gif +0 -0
  41. data/app/assets/images/dm_core/flags/bz.gif +0 -0
  42. data/app/assets/images/dm_core/flags/ca.gif +0 -0
  43. data/app/assets/images/dm_core/flags/cc.gif +0 -0
  44. data/app/assets/images/dm_core/flags/cd.gif +0 -0
  45. data/app/assets/images/dm_core/flags/cf.gif +0 -0
  46. data/app/assets/images/dm_core/flags/cg.gif +0 -0
  47. data/app/assets/images/dm_core/flags/ch.gif +0 -0
  48. data/app/assets/images/dm_core/flags/ci.gif +0 -0
  49. data/app/assets/images/dm_core/flags/ck.gif +0 -0
  50. data/app/assets/images/dm_core/flags/cl.gif +0 -0
  51. data/app/assets/images/dm_core/flags/cm.gif +0 -0
  52. data/app/assets/images/dm_core/flags/cn.gif +0 -0
  53. data/app/assets/images/dm_core/flags/co.gif +0 -0
  54. data/app/assets/images/dm_core/flags/cr.gif +0 -0
  55. data/app/assets/images/dm_core/flags/cs.gif +0 -0
  56. data/app/assets/images/dm_core/flags/cu.gif +0 -0
  57. data/app/assets/images/dm_core/flags/cv.gif +0 -0
  58. data/app/assets/images/dm_core/flags/cx.gif +0 -0
  59. data/app/assets/images/dm_core/flags/cy.gif +0 -0
  60. data/app/assets/images/dm_core/flags/cz.gif +0 -0
  61. data/app/assets/images/dm_core/flags/de.gif +0 -0
  62. data/app/assets/images/dm_core/flags/dj.gif +0 -0
  63. data/app/assets/images/dm_core/flags/dk.gif +0 -0
  64. data/app/assets/images/dm_core/flags/dm.gif +0 -0
  65. data/app/assets/images/dm_core/flags/do.gif +0 -0
  66. data/app/assets/images/dm_core/flags/dz.gif +0 -0
  67. data/app/assets/images/dm_core/flags/ec.gif +0 -0
  68. data/app/assets/images/dm_core/flags/ee.gif +0 -0
  69. data/app/assets/images/dm_core/flags/eg.gif +0 -0
  70. data/app/assets/images/dm_core/flags/eh.gif +0 -0
  71. data/app/assets/images/dm_core/flags/en.gif +0 -0
  72. data/app/assets/images/dm_core/flags/england.gif +0 -0
  73. data/app/assets/images/dm_core/flags/er.gif +0 -0
  74. data/app/assets/images/dm_core/flags/es.gif +0 -0
  75. data/app/assets/images/dm_core/flags/et.gif +0 -0
  76. data/app/assets/images/dm_core/flags/fam.gif +0 -0
  77. data/app/assets/images/dm_core/flags/fi.gif +0 -0
  78. data/app/assets/images/dm_core/flags/fj.gif +0 -0
  79. data/app/assets/images/dm_core/flags/fk.gif +0 -0
  80. data/app/assets/images/dm_core/flags/fm.gif +0 -0
  81. data/app/assets/images/dm_core/flags/fo.gif +0 -0
  82. data/app/assets/images/dm_core/flags/fr.gif +0 -0
  83. data/app/assets/images/dm_core/flags/ga.gif +0 -0
  84. data/app/assets/images/dm_core/flags/gb.gif +0 -0
  85. data/app/assets/images/dm_core/flags/gd.gif +0 -0
  86. data/app/assets/images/dm_core/flags/ge.gif +0 -0
  87. data/app/assets/images/dm_core/flags/gh.gif +0 -0
  88. data/app/assets/images/dm_core/flags/gi.gif +0 -0
  89. data/app/assets/images/dm_core/flags/gl.gif +0 -0
  90. data/app/assets/images/dm_core/flags/gm.gif +0 -0
  91. data/app/assets/images/dm_core/flags/gn.gif +0 -0
  92. data/app/assets/images/dm_core/flags/gp.gif +0 -0
  93. data/app/assets/images/dm_core/flags/gq.gif +0 -0
  94. data/app/assets/images/dm_core/flags/gr.gif +0 -0
  95. data/app/assets/images/dm_core/flags/gs.gif +0 -0
  96. data/app/assets/images/dm_core/flags/gt.gif +0 -0
  97. data/app/assets/images/dm_core/flags/gu.gif +0 -0
  98. data/app/assets/images/dm_core/flags/gw.gif +0 -0
  99. data/app/assets/images/dm_core/flags/gy.gif +0 -0
  100. data/app/assets/images/dm_core/flags/hk.gif +0 -0
  101. data/app/assets/images/dm_core/flags/hn.gif +0 -0
  102. data/app/assets/images/dm_core/flags/hr.gif +0 -0
  103. data/app/assets/images/dm_core/flags/ht.gif +0 -0
  104. data/app/assets/images/dm_core/flags/hu.gif +0 -0
  105. data/app/assets/images/dm_core/flags/id.gif +0 -0
  106. data/app/assets/images/dm_core/flags/ie.gif +0 -0
  107. data/app/assets/images/dm_core/flags/il.gif +0 -0
  108. data/app/assets/images/dm_core/flags/in.gif +0 -0
  109. data/app/assets/images/dm_core/flags/io.gif +0 -0
  110. data/app/assets/images/dm_core/flags/iq.gif +0 -0
  111. data/app/assets/images/dm_core/flags/ir.gif +0 -0
  112. data/app/assets/images/dm_core/flags/is.gif +0 -0
  113. data/app/assets/images/dm_core/flags/it.gif +0 -0
  114. data/app/assets/images/dm_core/flags/ja.gif +0 -0
  115. data/app/assets/images/dm_core/flags/jm.gif +0 -0
  116. data/app/assets/images/dm_core/flags/jo.gif +0 -0
  117. data/app/assets/images/dm_core/flags/ke.gif +0 -0
  118. data/app/assets/images/dm_core/flags/kg.gif +0 -0
  119. data/app/assets/images/dm_core/flags/kh.gif +0 -0
  120. data/app/assets/images/dm_core/flags/ki.gif +0 -0
  121. data/app/assets/images/dm_core/flags/km.gif +0 -0
  122. data/app/assets/images/dm_core/flags/kn.gif +0 -0
  123. data/app/assets/images/dm_core/flags/kp.gif +0 -0
  124. data/app/assets/images/dm_core/flags/kr.gif +0 -0
  125. data/app/assets/images/dm_core/flags/kw.gif +0 -0
  126. data/app/assets/images/dm_core/flags/ky.gif +0 -0
  127. data/app/assets/images/dm_core/flags/kz.gif +0 -0
  128. data/app/assets/images/dm_core/flags/la.gif +0 -0
  129. data/app/assets/images/dm_core/flags/lb.gif +0 -0
  130. data/app/assets/images/dm_core/flags/lc.gif +0 -0
  131. data/app/assets/images/dm_core/flags/li.gif +0 -0
  132. data/app/assets/images/dm_core/flags/lk.gif +0 -0
  133. data/app/assets/images/dm_core/flags/lr.gif +0 -0
  134. data/app/assets/images/dm_core/flags/ls.gif +0 -0
  135. data/app/assets/images/dm_core/flags/lt.gif +0 -0
  136. data/app/assets/images/dm_core/flags/lu.gif +0 -0
  137. data/app/assets/images/dm_core/flags/lv.gif +0 -0
  138. data/app/assets/images/dm_core/flags/ly.gif +0 -0
  139. data/app/assets/images/dm_core/flags/ma.gif +0 -0
  140. data/app/assets/images/dm_core/flags/mc.gif +0 -0
  141. data/app/assets/images/dm_core/flags/md.gif +0 -0
  142. data/app/assets/images/dm_core/flags/mg.gif +0 -0
  143. data/app/assets/images/dm_core/flags/mh.gif +0 -0
  144. data/app/assets/images/dm_core/flags/mk.gif +0 -0
  145. data/app/assets/images/dm_core/flags/ml.gif +0 -0
  146. data/app/assets/images/dm_core/flags/mm.gif +0 -0
  147. data/app/assets/images/dm_core/flags/mn.gif +0 -0
  148. data/app/assets/images/dm_core/flags/mo.gif +0 -0
  149. data/app/assets/images/dm_core/flags/mp.gif +0 -0
  150. data/app/assets/images/dm_core/flags/mq.gif +0 -0
  151. data/app/assets/images/dm_core/flags/mr.gif +0 -0
  152. data/app/assets/images/dm_core/flags/ms.gif +0 -0
  153. data/app/assets/images/dm_core/flags/mt.gif +0 -0
  154. data/app/assets/images/dm_core/flags/mu.gif +0 -0
  155. data/app/assets/images/dm_core/flags/mv.gif +0 -0
  156. data/app/assets/images/dm_core/flags/mw.gif +0 -0
  157. data/app/assets/images/dm_core/flags/mx.gif +0 -0
  158. data/app/assets/images/dm_core/flags/my.gif +0 -0
  159. data/app/assets/images/dm_core/flags/mz.gif +0 -0
  160. data/app/assets/images/dm_core/flags/na.gif +0 -0
  161. data/app/assets/images/dm_core/flags/nc.gif +0 -0
  162. data/app/assets/images/dm_core/flags/ne.gif +0 -0
  163. data/app/assets/images/dm_core/flags/nf.gif +0 -0
  164. data/app/assets/images/dm_core/flags/ng.gif +0 -0
  165. data/app/assets/images/dm_core/flags/ni.gif +0 -0
  166. data/app/assets/images/dm_core/flags/nl.gif +0 -0
  167. data/app/assets/images/dm_core/flags/no.gif +0 -0
  168. data/app/assets/images/dm_core/flags/np.gif +0 -0
  169. data/app/assets/images/dm_core/flags/nr.gif +0 -0
  170. data/app/assets/images/dm_core/flags/nu.gif +0 -0
  171. data/app/assets/images/dm_core/flags/nz.gif +0 -0
  172. data/app/assets/images/dm_core/flags/om.gif +0 -0
  173. data/app/assets/images/dm_core/flags/pa.gif +0 -0
  174. data/app/assets/images/dm_core/flags/pe.gif +0 -0
  175. data/app/assets/images/dm_core/flags/pf.gif +0 -0
  176. data/app/assets/images/dm_core/flags/pg.gif +0 -0
  177. data/app/assets/images/dm_core/flags/ph.gif +0 -0
  178. data/app/assets/images/dm_core/flags/pk.gif +0 -0
  179. data/app/assets/images/dm_core/flags/pl.gif +0 -0
  180. data/app/assets/images/dm_core/flags/pm.gif +0 -0
  181. data/app/assets/images/dm_core/flags/pn.gif +0 -0
  182. data/app/assets/images/dm_core/flags/pr.gif +0 -0
  183. data/app/assets/images/dm_core/flags/ps.gif +0 -0
  184. data/app/assets/images/dm_core/flags/pt.gif +0 -0
  185. data/app/assets/images/dm_core/flags/pw.gif +0 -0
  186. data/app/assets/images/dm_core/flags/py.gif +0 -0
  187. data/app/assets/images/dm_core/flags/qa.gif +0 -0
  188. data/app/assets/images/dm_core/flags/ro.gif +0 -0
  189. data/app/assets/images/dm_core/flags/ru.gif +0 -0
  190. data/app/assets/images/dm_core/flags/rw.gif +0 -0
  191. data/app/assets/images/dm_core/flags/sa.gif +0 -0
  192. data/app/assets/images/dm_core/flags/sb.gif +0 -0
  193. data/app/assets/images/dm_core/flags/sc.gif +0 -0
  194. data/app/assets/images/dm_core/flags/scotland.gif +0 -0
  195. data/app/assets/images/dm_core/flags/sd.gif +0 -0
  196. data/app/assets/images/dm_core/flags/se.gif +0 -0
  197. data/app/assets/images/dm_core/flags/sg.gif +0 -0
  198. data/app/assets/images/dm_core/flags/sh.gif +0 -0
  199. data/app/assets/images/dm_core/flags/si.gif +0 -0
  200. data/app/assets/images/dm_core/flags/sk.gif +0 -0
  201. data/app/assets/images/dm_core/flags/sl.gif +0 -0
  202. data/app/assets/images/dm_core/flags/sm.gif +0 -0
  203. data/app/assets/images/dm_core/flags/sn.gif +0 -0
  204. data/app/assets/images/dm_core/flags/so.gif +0 -0
  205. data/app/assets/images/dm_core/flags/sr.gif +0 -0
  206. data/app/assets/images/dm_core/flags/st.gif +0 -0
  207. data/app/assets/images/dm_core/flags/sv.gif +0 -0
  208. data/app/assets/images/dm_core/flags/sy.gif +0 -0
  209. data/app/assets/images/dm_core/flags/sz.gif +0 -0
  210. data/app/assets/images/dm_core/flags/tc.gif +0 -0
  211. data/app/assets/images/dm_core/flags/td.gif +0 -0
  212. data/app/assets/images/dm_core/flags/tf.gif +0 -0
  213. data/app/assets/images/dm_core/flags/tg.gif +0 -0
  214. data/app/assets/images/dm_core/flags/th.gif +0 -0
  215. data/app/assets/images/dm_core/flags/tj.gif +0 -0
  216. data/app/assets/images/dm_core/flags/tk.gif +0 -0
  217. data/app/assets/images/dm_core/flags/tl.gif +0 -0
  218. data/app/assets/images/dm_core/flags/tm.gif +0 -0
  219. data/app/assets/images/dm_core/flags/tn.gif +0 -0
  220. data/app/assets/images/dm_core/flags/to.gif +0 -0
  221. data/app/assets/images/dm_core/flags/tr.gif +0 -0
  222. data/app/assets/images/dm_core/flags/tt.gif +0 -0
  223. data/app/assets/images/dm_core/flags/tv.gif +0 -0
  224. data/app/assets/images/dm_core/flags/tw.gif +0 -0
  225. data/app/assets/images/dm_core/flags/tz.gif +0 -0
  226. data/app/assets/images/dm_core/flags/ua.gif +0 -0
  227. data/app/assets/images/dm_core/flags/ug.gif +0 -0
  228. data/app/assets/images/dm_core/flags/um.gif +0 -0
  229. data/app/assets/images/dm_core/flags/us.gif +0 -0
  230. data/app/assets/images/dm_core/flags/uy.gif +0 -0
  231. data/app/assets/images/dm_core/flags/uz.gif +0 -0
  232. data/app/assets/images/dm_core/flags/va.gif +0 -0
  233. data/app/assets/images/dm_core/flags/vc.gif +0 -0
  234. data/app/assets/images/dm_core/flags/ve.gif +0 -0
  235. data/app/assets/images/dm_core/flags/vg.gif +0 -0
  236. data/app/assets/images/dm_core/flags/vi.gif +0 -0
  237. data/app/assets/images/dm_core/flags/vn.gif +0 -0
  238. data/app/assets/images/dm_core/flags/vu.gif +0 -0
  239. data/app/assets/images/dm_core/flags/wales.gif +0 -0
  240. data/app/assets/images/dm_core/flags/wf.gif +0 -0
  241. data/app/assets/images/dm_core/flags/ws.gif +0 -0
  242. data/app/assets/images/dm_core/flags/ye.gif +0 -0
  243. data/app/assets/images/dm_core/flags/yt.gif +0 -0
  244. data/app/assets/images/dm_core/flags/za.gif +0 -0
  245. data/app/assets/images/dm_core/flags/zm.gif +0 -0
  246. data/app/assets/images/dm_core/flags/zw.gif +0 -0
  247. data/app/assets/images/dm_core/user.gif +0 -0
  248. data/app/assets/javascripts/dm_core/admin.js +223 -0
  249. data/app/assets/javascripts/dm_core/admin_extra.js.coffee +118 -0
  250. data/app/assets/javascripts/dm_core/application.js +14 -0
  251. data/app/assets/javascripts/dm_core/common_js.js.coffee +61 -0
  252. data/app/assets/javascripts/dm_core/underscore-1.4.4-min.js +1 -0
  253. data/app/assets/javascripts/dm_core/underscore-1.4.4.js +1227 -0
  254. data/app/assets/stylesheets/dm_core/admin.css +250 -0
  255. data/app/assets/stylesheets/dm_core/application.css +31 -0
  256. data/app/assets/stylesheets/dm_core/font-awesome.css +1479 -0
  257. data/app/assets/stylesheets/dm_core/font/FontAwesome.otf +0 -0
  258. data/app/assets/stylesheets/dm_core/font/fontawesome-webfont.eot +0 -0
  259. data/app/assets/stylesheets/dm_core/font/fontawesome-webfont.svg +399 -0
  260. data/app/assets/stylesheets/dm_core/font/fontawesome-webfont.ttf +0 -0
  261. data/app/assets/stylesheets/dm_core/font/fontawesome-webfont.woff +0 -0
  262. data/app/controllers/dm_core/admin/accounts_controller.rb +125 -0
  263. data/app/controllers/dm_core/admin/admin_controller.rb +133 -0
  264. data/app/controllers/dm_core/admin/comments_controller.rb +70 -0
  265. data/app/controllers/dm_core/admin/dashboard_controller.rb +38 -0
  266. data/app/controllers/dm_core/admin/system_controller.rb +44 -0
  267. data/app/controllers/dm_core/admin/users_controller.rb +106 -0
  268. data/app/controllers/dm_core/application_controller.rb +253 -0
  269. data/app/controllers/dm_core/concerns/profile_controller.rb +41 -0
  270. data/app/controllers/dm_core/profile_controller.rb +8 -0
  271. data/app/datatables/user_datatable.rb +75 -0
  272. data/app/helpers/devise_helper.rb +25 -0
  273. data/app/helpers/dm_core/account_helper.rb +70 -0
  274. data/app/helpers/dm_core/admin/application_helper.rb +23 -0
  275. data/app/helpers/dm_core/application_helper.rb +58 -0
  276. data/app/helpers/dm_core/liquid_helper.rb +79 -0
  277. data/app/helpers/dm_core/params_helper.rb +19 -0
  278. data/app/helpers/dm_core/render_helper.rb +104 -0
  279. data/app/helpers/dm_core/url_helper.rb +189 -0
  280. data/app/helpers/dm_utilities/currency_helper.rb +24 -0
  281. data/app/helpers/dm_utilities/date_helper.rb +72 -0
  282. data/app/inputs/code_editor_input.rb +51 -0
  283. data/app/inputs/text_full_width_input.rb +9 -0
  284. data/app/inputs/toggle_checked_input.rb +9 -0
  285. data/app/inputs/toggle_input.rb +9 -0
  286. data/app/mailers/dm_core/site_mailer.rb +18 -0
  287. data/app/models/account.rb +241 -0
  288. data/app/models/activity.rb +10 -0
  289. data/app/models/address.rb +24 -0
  290. data/app/models/category.rb +18 -0
  291. data/app/models/comment.rb +24 -0
  292. data/app/models/custom_field.rb +99 -0
  293. data/app/models/custom_field_def.rb +61 -0
  294. data/app/models/dm_core/concerns/ability.rb +17 -0
  295. data/app/models/dm_core/concerns/defines_custom_fields.rb +17 -0
  296. data/app/models/dm_core/concerns/friendly_id.rb +57 -0
  297. data/app/models/dm_core/concerns/has_custom_fields.rb +28 -0
  298. data/app/models/dm_core/concerns/public_private.rb +151 -0
  299. data/app/models/dm_core/concerns/user.rb +144 -0
  300. data/app/models/dm_core/concerns/user_profile.rb +113 -0
  301. data/app/models/dm_core/concerns/user_site_profile.rb +65 -0
  302. data/app/models/dm_core/country.rb +8 -0
  303. data/app/models/dm_core/language.rb +59 -0
  304. data/app/models/dm_core/permitted_params.rb +52 -0
  305. data/app/models/follow.rb +13 -0
  306. data/app/models/liquid_validator.rb +26 -0
  307. data/app/models/payment_history.rb +57 -0
  308. data/app/models/presence_default_locale_validator.rb +12 -0
  309. data/app/models/role.rb +12 -0
  310. data/app/models/system_email.rb +15 -0
  311. data/app/models/ultracart/notification.rb +107 -0
  312. data/app/models/ultracart/payment_history.rb +55 -0
  313. data/app/models/user.rb +22 -0
  314. data/app/models/user_profile.rb +9 -0
  315. data/app/models/user_site_profile.rb +11 -0
  316. data/app/presenters/base_presenter.rb +30 -0
  317. data/app/presenters/comment_presenter.rb +20 -0
  318. data/app/presenters/user_presenter.rb +48 -0
  319. data/app/uploaders/avatar_uploader.rb +75 -0
  320. data/app/views/devise/mailer/confirmation_instructions.html.erb +7 -0
  321. data/app/views/devise/mailer/confirmation_instructions.text.erb +7 -0
  322. data/app/views/devise/mailer/reset_password_instructions.html.erb +9 -0
  323. data/app/views/devise/mailer/reset_password_instructions.text.erb +9 -0
  324. data/app/views/devise/mailer/unlock_instructions.html.erb +7 -0
  325. data/app/views/devise/mailer/unlock_instructions.text.erb +7 -0
  326. data/app/views/dm_core/admin/accounts/_settings_menu.html.erb +24 -0
  327. data/app/views/dm_core/admin/accounts/analytics.html.erb +38 -0
  328. data/app/views/dm_core/admin/accounts/email.html.erb +26 -0
  329. data/app/views/dm_core/admin/accounts/general.html.erb +22 -0
  330. data/app/views/dm_core/admin/accounts/media.html.erb +37 -0
  331. data/app/views/dm_core/admin/accounts/metadata.html.erb +22 -0
  332. data/app/views/dm_core/admin/comments/_comment.html.erb +14 -0
  333. data/app/views/dm_core/admin/comments/_comment_edit_form.html.erb +3 -0
  334. data/app/views/dm_core/admin/comments/_comment_form.html.erb +15 -0
  335. data/app/views/dm_core/admin/comments/_comment_list.html.erb +5 -0
  336. data/app/views/dm_core/admin/comments/_comment_section.html.erb +7 -0
  337. data/app/views/dm_core/admin/comments/create.js.erb +4 -0
  338. data/app/views/dm_core/admin/comments/destroy.js.erb +1 -0
  339. data/app/views/dm_core/admin/comments/edit.js.erb +2 -0
  340. data/app/views/dm_core/admin/comments/update.js.erb +2 -0
  341. data/app/views/dm_core/admin/custom_fields/_check_box_collection.html.erb +4 -0
  342. data/app/views/dm_core/admin/custom_fields/_custom_field_def_fields.html.erb +34 -0
  343. data/app/views/dm_core/admin/custom_fields/_divider.html.erb +1 -0
  344. data/app/views/dm_core/admin/custom_fields/_number_field.html.erb +4 -0
  345. data/app/views/dm_core/admin/custom_fields/_radio_buttons.html.erb +4 -0
  346. data/app/views/dm_core/admin/custom_fields/_select.html.erb +4 -0
  347. data/app/views/dm_core/admin/custom_fields/_text_area.html.erb +4 -0
  348. data/app/views/dm_core/admin/custom_fields/_text_field.html.erb +4 -0
  349. data/app/views/dm_core/admin/dashboard/_index_sidebar.html.erb +22 -0
  350. data/app/views/dm_core/admin/dashboard/_widget_recent_new_users.html.erb +23 -0
  351. data/app/views/dm_core/admin/dashboard/_widget_recent_user_activity.html.erb +21 -0
  352. data/app/views/dm_core/admin/dashboard/index.html.erb +7 -0
  353. data/app/views/dm_core/admin/dashboard/update_site_assets.html.erb +5 -0
  354. data/app/views/dm_core/admin/shared/_header_stats_new_users.html.erb +2 -0
  355. data/app/views/dm_core/admin/shared/_header_stats_user_activity.html.erb +2 -0
  356. data/app/views/dm_core/admin/system/show.html.erb +23 -0
  357. data/app/views/dm_core/admin/users/_form.html.erb +44 -0
  358. data/app/views/dm_core/admin/users/edit.html.erb +201 -0
  359. data/app/views/dm_core/admin/users/index.html.erb +30 -0
  360. data/app/views/dm_core/profile/_profile_sidebar.html.erb +6 -0
  361. data/app/views/dm_core/profile/account.html.erb +38 -0
  362. data/app/views/dm_core/profile/details.html.erb +38 -0
  363. data/app/views/layouts/dm_core/application.html.erb +14 -0
  364. data/app/views/layouts/dm_core/maintenance.html.erb +31 -0
  365. data/app/views/layouts/email_templates/default_email_layout.html.erb +289 -0
  366. data/config/initializers/_dm_core.rb +7 -0
  367. data/config/initializers/carrierwave.rb +33 -0
  368. data/config/initializers/devise.rb +252 -0
  369. data/config/initializers/friendly_id.rb +88 -0
  370. data/config/initializers/globalize_easy_accessors.rb +67 -0
  371. data/config/initializers/globalize_papertrail_fix.rb +20 -0
  372. data/config/initializers/globalize_reflections.rb +22 -0
  373. data/config/initializers/rolify.rb +8 -0
  374. data/config/initializers/simple_form.rb +161 -0
  375. data/config/initializers/simple_form_amsterdam.rb +31 -0
  376. data/config/initializers/simple_form_bootstrap.rb +87 -0
  377. data/config/initializers/simple_form_bootstrap3.rb +175 -0
  378. data/config/initializers/will_paginate.rb +87 -0
  379. data/config/locales/custom.cs.yml +82 -0
  380. data/config/locales/custom.de.yml +82 -0
  381. data/config/locales/custom.en.yml +84 -0
  382. data/config/locales/custom.fi.yml +84 -0
  383. data/config/locales/custom.ja.yml +84 -0
  384. data/config/locales/devise.cs.yml +70 -0
  385. data/config/locales/devise.de.yml +60 -0
  386. data/config/locales/devise.en.yml +59 -0
  387. data/config/locales/devise.fi.yml +57 -0
  388. data/config/locales/devise.ja.yml +102 -0
  389. data/config/locales/rails.cs.yml +211 -0
  390. data/config/locales/rails.de-AT.yml +203 -0
  391. data/config/locales/rails.de.yml +203 -0
  392. data/config/locales/rails.en-GB.yml +205 -0
  393. data/config/locales/rails.en-IN.yml +205 -0
  394. data/config/locales/rails.en.yml +205 -0
  395. data/config/locales/rails.fi.yml +199 -0
  396. data/config/locales/rails.fr-CH.yml +207 -0
  397. data/config/locales/rails.fr.yml +215 -0
  398. data/config/locales/rails.ja.yml +197 -0
  399. data/config/locales/simple_form.cs.yml +26 -0
  400. data/config/locales/simple_form.de.yml +26 -0
  401. data/config/locales/simple_form.en.yml +26 -0
  402. data/config/locales/simple_form.fi.yml +26 -0
  403. data/config/locales/simple_form.ja.yml +26 -0
  404. data/config/routes.rb +33 -0
  405. data/db/globalize_seed_data.sql +76 -0
  406. data/db/migrate/20121023202117_add_globalize_countries.rb +49 -0
  407. data/db/migrate/20121028125329_devise_create_users.rb +45 -0
  408. data/db/migrate/20121028125831_add_user_fields.rb +13 -0
  409. data/db/migrate/20121028153317_rolify_create_roles.rb +19 -0
  410. data/db/migrate/20121105205634_add_last_access.rb +9 -0
  411. data/db/migrate/20121110213512_create_versions.rb +18 -0
  412. data/db/migrate/20121110213513_add_object_changes_column_to_versions.rb +11 -0
  413. data/db/migrate/20130206121535_create_dm_core_accounts.rb +12 -0
  414. data/db/migrate/20130206223323_add_account_to_users.rb +8 -0
  415. data/db/migrate/20130207170247_create_preferences.rb +12 -0
  416. data/db/migrate/20130321144726_create_comments.rb +21 -0
  417. data/db/migrate/20130402203739_add_activity.rb +20 -0
  418. data/db/migrate/20130415095617_add_type_to_comments.rb +8 -0
  419. data/db/migrate/20130429191051_add_category.rb +27 -0
  420. data/db/migrate/20130513112751_create_email_table.rb +25 -0
  421. data/db/migrate/20130516143539_add_user_profile.rb +45 -0
  422. data/db/migrate/20130518155712_add_profile_email.rb +13 -0
  423. data/db/migrate/20130620145610_create_payment_history.rb +36 -0
  424. data/db/migrate/20130625091108_change_anchor_field.rb +9 -0
  425. data/db/migrate/20130628112848_create_user_site_profile.rb +26 -0
  426. data/db/migrate/20130708150236_add_avatar.rb +11 -0
  427. data/db/migrate/20130914132041_add_notify_to_payment_history.rb +7 -0
  428. data/db/migrate/20140105133446_acts_as_votable_migration.rb +27 -0
  429. data/db/migrate/20140107112418_add_user_site_profile_uuid.rb +18 -0
  430. data/db/migrate/20140129110547_add_invoice_id.rb +6 -0
  431. data/db/migrate/20140201092656_acts_as_follower_migration.rb +17 -0
  432. data/db/migrate/20140203131320_rename_invoice_id.rb +11 -0
  433. data/db/migrate/20140210195143_add_core_addresses.rb +17 -0
  434. data/db/migrate/20140411190454_papertrail_increase_column.rb +8 -0
  435. data/db/migrate/20140501160009_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb +31 -0
  436. data/db/migrate/20140501160010_add_missing_unique_indices.acts_as_taggable_on_engine.rb +22 -0
  437. data/db/migrate/20140501160011_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb +15 -0
  438. data/db/migrate/20140529164730_create_custom_fields.rb +39 -0
  439. data/db/migrate/20140709145503_add_missing_taggable_index.acts_as_taggable_on_engine.rb +10 -0
  440. data/db/migrate/20141216094639_add_favored_locale.rb +18 -0
  441. data/db/migrate/20160128094739_update_papertrail_v4.rb +73 -0
  442. data/db/migrate/20160630095745_create_delayed_jobs.rb +22 -0
  443. data/db/migrate/20160821150111_index_foreign_keys_in_core_accounts.rb +5 -0
  444. data/db/migrate/20160821150113_index_foreign_keys_in_core_addresses.rb +5 -0
  445. data/db/migrate/20160821150114_index_foreign_keys_in_core_categories.rb +5 -0
  446. data/db/migrate/20160821150115_index_foreign_keys_in_core_comments.rb +5 -0
  447. data/db/migrate/20160821150116_index_foreign_keys_in_core_custom_fields.rb +5 -0
  448. data/db/migrate/20160821150117_index_foreign_keys_in_core_payment_histories.rb +7 -0
  449. data/db/migrate/20160821150118_index_foreign_keys_in_core_system_email_translations.rb +5 -0
  450. data/db/migrate/20160821150119_index_foreign_keys_in_core_system_emails.rb +6 -0
  451. data/db/migrate/20160821150128_index_foreign_keys_in_preferences.rb +5 -0
  452. data/db/migrate/20160821150129_index_foreign_keys_in_roles.rb +5 -0
  453. data/db/migrate/20160821150130_index_foreign_keys_in_taggings.rb +5 -0
  454. data/db/migrate/20160821150131_index_foreign_keys_in_user_profiles.rb +7 -0
  455. data/db/migrate/20160821150132_index_foreign_keys_in_user_site_profiles.rb +6 -0
  456. data/db/migrate/20160821150133_index_foreign_keys_in_users_roles.rb +5 -0
  457. data/db/migrate/20160821150134_index_foreign_keys_in_version_associations.rb +5 -0
  458. data/db/migrate/20160821150135_index_foreign_keys_in_versions.rb +5 -0
  459. data/db/seeds.rb +433 -0
  460. data/db/seeds/globalize_countries.rb +239 -0
  461. data/db/seeds/globalize_languages.rb +186 -0
  462. data/lib/dm_core.rb +38 -0
  463. data/lib/dm_core/csv_exporter.rb +210 -0
  464. data/lib/dm_core/csv_importer.rb +16 -0
  465. data/lib/dm_core/engine.rb +51 -0
  466. data/lib/dm_core/liquid_extensions.rb +125 -0
  467. data/lib/dm_core/nls.rb +31 -0
  468. data/lib/dm_core/scio_excel.rb +501 -0
  469. data/lib/dm_core/state_select.rb +135 -0
  470. data/lib/dm_core/version.rb +3 -0
  471. data/lib/tasks/dm_core_tasks.rake +60 -0
  472. data/spec/dummy/README.rdoc +28 -0
  473. data/spec/dummy/Rakefile +6 -0
  474. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  475. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  476. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  477. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  478. data/spec/dummy/app/models/ability.rb +10 -0
  479. data/spec/dummy/app/models/user.rb +6 -0
  480. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  481. data/spec/dummy/bin/bundle +3 -0
  482. data/spec/dummy/bin/rails +4 -0
  483. data/spec/dummy/bin/rake +4 -0
  484. data/spec/dummy/config.ru +4 -0
  485. data/spec/dummy/config/application.rb +27 -0
  486. data/spec/dummy/config/boot.rb +5 -0
  487. data/spec/dummy/config/database.yml +25 -0
  488. data/spec/dummy/config/environment.rb +5 -0
  489. data/spec/dummy/config/environments/development.rb +37 -0
  490. data/spec/dummy/config/environments/production.rb +82 -0
  491. data/spec/dummy/config/environments/test.rb +39 -0
  492. data/spec/dummy/config/initializers/assets.rb +8 -0
  493. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  494. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  495. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  496. data/spec/dummy/config/initializers/inflections.rb +16 -0
  497. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  498. data/spec/dummy/config/initializers/session_store.rb +3 -0
  499. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  500. data/spec/dummy/config/locales/en.yml +23 -0
  501. data/spec/dummy/config/routes.rb +11 -0
  502. data/spec/dummy/config/secrets.yml +22 -0
  503. data/spec/dummy/db/development.sqlite3 +0 -0
  504. data/spec/dummy/db/schema.rb +399 -0
  505. data/spec/dummy/db/test.sqlite3 +0 -0
  506. data/spec/dummy/log/test.log +374 -0
  507. data/spec/dummy/public/404.html +67 -0
  508. data/spec/dummy/public/422.html +67 -0
  509. data/spec/dummy/public/500.html +66 -0
  510. data/spec/dummy/public/favicon.ico +0 -0
  511. data/spec/factories/accounts.rb +9 -0
  512. data/spec/factories/user_profiles.rb +10 -0
  513. data/spec/factories/users.rb +19 -0
  514. data/spec/helpers/account_helper_spec.rb +50 -0
  515. data/spec/models/account_spec.rb +20 -0
  516. data/spec/models/user_spec.rb +99 -0
  517. data/spec/rails_helper.rb +70 -0
  518. data/spec/spec_helper.rb +85 -0
  519. data/spec/support/accounts.rb +19 -0
  520. data/spec/support/devise.rb +44 -0
  521. data/spec/support/fix_locale.rb +57 -0
  522. metadata +1124 -0
@@ -0,0 +1,10 @@
1
+ #------------------------------------------------------------------------------
2
+ class Activity < ActiveRecord::Base
3
+
4
+ self.table_name = 'core_activities'
5
+
6
+ default_scope { where(account_id: Account.current.id).order("created_at ASC") }
7
+
8
+ belongs_to :user
9
+
10
+ end
@@ -0,0 +1,24 @@
1
+ class Address < ActiveRecord::Base
2
+
3
+ self.table_name = 'core_addresses'
4
+ belongs_to :addressable, :polymorphic => true
5
+
6
+ attr_accessor :name
7
+
8
+ biggs :postal_address,
9
+ :recipient => :name,
10
+ :country => :country_code,
11
+ :street => Proc.new {|address| "#{address.line1} #{address.line2}" }
12
+
13
+ #------------------------------------------------------------------------------
14
+ def to_s(name_to_use = '')
15
+ self.name = name_to_use
16
+ postal_address.strip
17
+ end
18
+
19
+ #------------------------------------------------------------------------------
20
+ def to_html(name_to_use = '')
21
+ # self.to_s(name_to_use).gsub("\n", "<br/>".html_safe)
22
+ self.to_s(name_to_use).split(/\n/).xss_aware_join('<br>'.html_safe)
23
+ end
24
+ end
@@ -0,0 +1,18 @@
1
+ #------------------------------------------------------------------------------
2
+ class Category < ActiveRecord::Base
3
+
4
+ self.table_name = 'core_categories'
5
+
6
+ include RankedModel
7
+ ranks :row_order, :with_same => :account_id
8
+
9
+ default_scope { where(account_id: Account.current.id) }
10
+ scope :ordered, -> { order('row_order ASC') }
11
+
12
+ # --- globalize
13
+ translates :name, :description, :fallbacks_for_empty_translations => true
14
+ globalize_accessors :locales => DmCore::Language.language_array
15
+
16
+ validates :name, presence_default_locale: true
17
+
18
+ end
@@ -0,0 +1,24 @@
1
+ # Generated from acts_as_commentable
2
+ #------------------------------------------------------------------------------
3
+ class Comment < ActiveRecord::Base
4
+ include ActsAsCommentable::Comment
5
+
6
+ self.table_name = 'core_comments'
7
+
8
+ belongs_to :commentable, :polymorphic => true, :counter_cache => true
9
+ has_ancestry :cache_depth => true
10
+
11
+ #--- don't add ordering to default scope, as it messes with calculating recent_comment
12
+ default_scope { where(account_id: Account.current.id) }
13
+
14
+ #--- NOTE: install the acts_as_votable plugin to vote on the quality of comments
15
+ #acts_as_voteable
16
+
17
+ #--- don't use a counter cache until you can seperate users per account
18
+ belongs_to :user #, :counter_cache => true
19
+ belongs_to :account
20
+
21
+ validates_presence_of :body
22
+ self.per_page = 10
23
+
24
+ end
@@ -0,0 +1,99 @@
1
+ # TODO The one problem I have with this is that when a field is empty, we still
2
+ # save the record to the database. The difficulty is that when the
3
+ # form is displayed, you need to have all the records there, ones that
4
+ # were saved and empty ones for those not saved, all in the proper order.
5
+ # This presents a challenge I'm not willing to tackle at this moment.
6
+ # But it should be done so that the database isn't cluttered with needless
7
+ # records.
8
+ #
9
+ # Note: We serialize the data. This makes it easy to store checkbox arrays, dates,
10
+ # etc, without having to worry about munging the data first.
11
+ #------------------------------------------------------------------------------
12
+ class CustomField < ActiveRecord::Base
13
+ self.table_name = 'core_custom_fields'
14
+ serialize :field_data
15
+
16
+ # acts_as_reportable
17
+
18
+ belongs_to :custom_field_def
19
+ belongs_to :owner, polymorphic: true
20
+
21
+ default_scope { where(account_id: Account.current.id) }
22
+
23
+ # before_save :prepare_data
24
+
25
+ delegate :field_type, to: :custom_field_def
26
+ delegate :name, to: :custom_field_def
27
+ delegate :label, to: :custom_field_def
28
+ delegate :description, to: :custom_field_def
29
+ delegate :required?, to: :custom_field_def
30
+ delegate :choice_list_array, to: :custom_field_def
31
+
32
+ # delegate :controldef, to: :custom_field_def
33
+ # delegate :leadin_text, to: :custom_field_def
34
+ # delegate :visible?, to: :custom_field_def
35
+ # delegate :divider?, to: :custom_field_def
36
+ # delegate :position, to: :custom_field_def
37
+ # delegate :show_in_list?, to: :custom_field_def
38
+
39
+ validates_presence_of :field_data, if: Proc.new {|field| field.required?}
40
+ validates_numericality_of :field_data, if: Proc.new {|field| field.field_type == 'number_field' && !field.field_data.blank?}
41
+ validate :checkbox_required, if: Proc.new {|field| field.field_type == 'check_box_collection' && field.required?}
42
+
43
+ #------------------------------------------------------------------------------
44
+ def initialize(*options, &block)
45
+ super(*options, &block)
46
+ # prepare_data
47
+ end
48
+
49
+ # Returns a munged value depending on the field type. Used when data is exported.
50
+ #------------------------------------------------------------------------------
51
+ def value
52
+ #--- if field is a country field, convert the country_id into real name
53
+ if custom_field_def.field_type == 'country'
54
+ Country.find(self.field_data.to_i).english_name
55
+ elsif self.field_data.is_a? Array
56
+ # make into a comma delimited string. remove any blank/nil entries
57
+ self.field_data.reject {|x| x.blank?}.join(', ')
58
+ else
59
+ self.field_data
60
+ end
61
+ end
62
+
63
+ #------------------------------------------------------------------------------
64
+ def checkbox_required
65
+ errors.add(:field_data, :blank) if self.value.blank?
66
+ end
67
+
68
+ # # Munge the data so that it's stored correctly
69
+ # #------------------------------------------------------------------------------
70
+ # def prepare_data
71
+ # #--- an array of values is stores as a comma delimited string
72
+ # self.field_data = self.field_data.join(', ') if self.field_data.class == Array
73
+ #
74
+ # # #--- if field is a date/time field, convert the date into database format
75
+ # # unless custom_field_def_id.nil?
76
+ # # field_def = CustomFieldDef.find(custom_field_def_id)
77
+ # # if field_def and !self.data.blank?
78
+ # # if field_def.fieldtype == 'date_time' or field_def.fieldtype == 'date'
79
+ # # self.data = Time.parse(self.data).to_s(:db)
80
+ # # elsif field_def.fieldtype == 'number_field'
81
+ # # p = NumberParser.new
82
+ # # self.data = p.extract(self.data.to_s)[0]
83
+ # # end
84
+ # # end
85
+ # # end
86
+ # end
87
+ #
88
+ # # Treat data as comma delimited, return it as an array of values
89
+ # #------------------------------------------------------------------------------
90
+ # def field_data_array
91
+ # self.field_data.nil? ? [] : self.field_data.split(',').collect { |item| item.strip }
92
+ # end
93
+ #
94
+ # #------------------------------------------------------------------------------
95
+ # def human_attribute_name(key)
96
+ # label.blank? ? 'Field' : "'#{nls(label, namespace: 'site_custom_field')}'"
97
+ # end
98
+
99
+ end
@@ -0,0 +1,61 @@
1
+ # Reference: "Handle Multiple Models in One Form" from "Advanced Rails Recipes"
2
+ # and http://railscasts.com/episodes/403-dynamic-forms
3
+ # and http://railscasts.com/episodes/196-nested-model-form-revised
4
+ # Note: tried to use coder: JSON for the store, but kept getting a
5
+ # "A JSON text must at least contain two octets!" exception (from new fields)
6
+ # so store in yaml format instead
7
+ #------------------------------------------------------------------------------
8
+ class CustomFieldDef < ActiveRecord::Base
9
+ self.table_name = 'core_custom_field_defs'
10
+
11
+ belongs_to :owner, polymorphic: true
12
+ has_many :custom_fields, dependent: :destroy
13
+ store :properties, accessors: [:choice_list, :valid_until]
14
+
15
+ include RankedModel
16
+ ranks :row_order, with_same: [:owner_id, :owner_type]
17
+ default_scope { where(account_id: Account.current.id) }
18
+
19
+ translates :label, :description, fallbacks_for_empty_translations: true
20
+ globalize_accessors locales: DmCore::Language.language_array
21
+
22
+ validates_presence_of :field_type
23
+ validates_length_of :field_type, maximum: 20
24
+
25
+ FIELD_TYPES = [ ['Text Field', 'text_field'],
26
+ ['Text Area', 'text_area'],
27
+ ['Number Field', 'number_field'],
28
+ ['Checkboxes', 'check_box_collection'],
29
+ ['Radio Buttons', 'radio_buttons'],
30
+ ['Drop Down Menu', 'select'],
31
+ ['Divider', 'divider']
32
+ # ['Date/Time Selection', 'date_time'],
33
+ # ['Date Selection', 'date'],
34
+ # ['Country Selection', 'country'],
35
+ ].freeze
36
+
37
+ #------------------------------------------------------------------------------
38
+ def divider?
39
+ fieldtype == 'divider'
40
+ end
41
+
42
+ #------------------------------------------------------------------------------
43
+ def choice_list_array
44
+ choice_list.split(',').collect { |item| item.strip }
45
+ end
46
+
47
+ # Text to use for the column during export or in reports. The label will
48
+ # be used if the 'name' attribute is blank
49
+ #------------------------------------------------------------------------------
50
+ def column_name
51
+ self.name.blank? ? self.label.to_s_default : self.name
52
+ end
53
+
54
+ # # custom field is visible if it's not disabled and it's still valid
55
+ # #------------------------------------------------------------------------------
56
+ # def visible?
57
+ # !(disabled? || (!valid_until.nil? && valid_until < Time.now.to_date))
58
+ # end
59
+ #
60
+
61
+ end
@@ -0,0 +1,17 @@
1
+ # Wrap core level specific CanCan rules. Should be included in the main app's
2
+ # Ability class.
3
+ #------------------------------------------------------------------------------
4
+ module DmCore
5
+ module Concerns
6
+ module Ability
7
+ def dm_core_abilities(user)
8
+ if user
9
+ if user.is_admin? || user.has_role?(:manager)
10
+ can :manage, :all
11
+ can :access_admin, :all
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ #------------------------------------------------------------------------------
2
+ module DmCore
3
+ module Concerns
4
+ module DefinesCustomFields
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ has_many :custom_field_defs, as: :owner, dependent: :destroy
9
+
10
+ accepts_nested_attributes_for :custom_field_defs, allow_destroy: true
11
+ end
12
+
13
+ module ClassMethods
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,57 @@
1
+ # FriendlyID support methods
2
+ # In general,
3
+ # - extends FriendlyID
4
+ # - requires slug to be present
5
+ # - normalizes slug using Babosa gem. Ensures normalized even if user inputed
6
+ # - indicates to generate a new slug if it's blank
7
+ #
8
+ # To use:
9
+ # extend FriendlyId
10
+ # include DmCore::Concerns::FriendlyId
11
+ #
12
+ # def model_slug
13
+ # send("title_#{Account.current.preferred_default_locale}")
14
+ # end
15
+
16
+ #------------------------------------------------------------------------------
17
+ module DmCore
18
+ module Concerns
19
+ module FriendlyId
20
+ extend ActiveSupport::Concern
21
+
22
+ included do
23
+
24
+ friendly_id :model_slug, use: :scoped, scope: :account_id
25
+ validates_presence_of :slug
26
+ before_save :normalize_slug
27
+
28
+ # Override this to provide what the slug value should be based on
29
+ #------------------------------------------------------------------------------
30
+ def model_slug
31
+ slug
32
+ end
33
+
34
+ # regenerate slug if it's blank
35
+ #------------------------------------------------------------------------------
36
+ def should_generate_new_friendly_id?
37
+ self.slug.blank?
38
+ end
39
+
40
+ # If user set slug sepcifically, we need to make sure it's been normalized
41
+ #------------------------------------------------------------------------------
42
+ def normalize_slug
43
+ self.slug = normalize_friendly_id(self.slug)
44
+ end
45
+
46
+ # use babosa gem (to_slug) to allow better handling of multi-language slugs
47
+ #------------------------------------------------------------------------------
48
+ def normalize_friendly_id(text)
49
+ text.to_s.to_slug.normalize.to_s
50
+ end
51
+ end
52
+
53
+ module ClassMethods
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,28 @@
1
+ #------------------------------------------------------------------------------
2
+ module DmCore
3
+ module Concerns
4
+ module HasCustomFields
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+
9
+ has_many :custom_fields, as: :owner, dependent: :destroy
10
+ accepts_nested_attributes_for :custom_fields
11
+
12
+ # Given an object that defines all the custom fields, builds any missing fields
13
+ # onto the custom_fields association.
14
+ #------------------------------------------------------------------------------
15
+ def build_missing_fields(defining_object)
16
+ existing_def_ids = custom_fields.map(&:custom_field_def_id) # can't use pluck
17
+ missing_field_defs = defining_object.custom_field_defs.reject {|x| existing_def_ids.include? x.id}
18
+ missing_field_defs.each do |field_def|
19
+ custom_fields.build(custom_field_def_id: field_def.id)
20
+ end
21
+ end
22
+ end
23
+
24
+ module ClassMethods
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,151 @@
1
+ # Implementation for public/protected/private and membership objects.
2
+ # "public" means it is available for everyone to see, login not required
3
+ # "protected" means it is available to anyone that is logged in
4
+ # "private" means it is hidden unless you are an explicit member of the object
5
+ # "subscription" means a paid subscription is required
6
+ #------------------------------------------------------------------------------
7
+ module DmCore
8
+ module Concerns
9
+ module PublicPrivate
10
+ extend ActiveSupport::Concern
11
+
12
+ # 'included do' causes the included code to be evaluated in the
13
+ # conext where it is included (post.rb), rather than be
14
+ # executed in the module's context (blorgh/concerns/models/post).
15
+ included do
16
+
17
+ scope :all_public, -> { where(is_public: true) } # includes public and protected
18
+ scope :by_public, -> { where(is_public: true, requires_login: false) }
19
+ scope :by_protected, -> { where(is_public: true, requires_login: true) }
20
+ scope :all_private, -> { where(is_public: false) } # includes private and subscription
21
+ scope :by_private, -> { where(is_public: false, requires_subscription: false) }
22
+ scope :by_subscription, -> { where(requires_subscription: true) }
23
+
24
+ # check if public (does not require login)
25
+ #------------------------------------------------------------------------------
26
+ def is_public?
27
+ is_public == true && requires_login == false
28
+ end
29
+
30
+ # check if protected (public and requires login)
31
+ #------------------------------------------------------------------------------
32
+ def is_protected?
33
+ is_public == true && requires_login == true
34
+ end
35
+
36
+ # check if private (not public and does not require login, or requires a subscription)
37
+ # we consider a requires subscription as private in this context
38
+ #------------------------------------------------------------------------------
39
+ def is_private?
40
+ is_public == false || (is_public == false && requires_subscription == true)
41
+ end
42
+
43
+ #------------------------------------------------------------------------------
44
+ def is_subscription_only?
45
+ requires_subscription == true
46
+ end
47
+
48
+ #------------------------------------------------------------------------------
49
+ def visibility_to_s
50
+ is_public? ? 'public' : is_subscription_only? ? 'subscription' : is_private? ? 'private' : 'protected'
51
+ end
52
+
53
+ # add user as a member. duplicates are not added automatically
54
+ #------------------------------------------------------------------------------
55
+ def add_member(user)
56
+ user.add_role(:member, self)
57
+ end
58
+
59
+ #------------------------------------------------------------------------------
60
+ def remove_member(user)
61
+ user.remove_role(:member, self)
62
+ end
63
+
64
+ # Is the user a member of this object?
65
+ #------------------------------------------------------------------------------
66
+ def member?(user)
67
+ user.has_role?(:member, self) || self.owner.try('member?', user)
68
+ end
69
+
70
+ #------------------------------------------------------------------------------
71
+ def member_count(which_ones = :all)
72
+ case which_ones
73
+ when :manual
74
+ ::User.with_role(:member, self).count
75
+ when :automatic
76
+ if is_subscription_only?
77
+ ::User.paid_subscribers.count
78
+ else
79
+ self.owner ? self.owner.member_count : 0
80
+ end
81
+ when :all
82
+ member_count(:manual) + member_count(:automatic)
83
+ end
84
+ end
85
+
86
+ # Return a list of users that have access
87
+ #------------------------------------------------------------------------------
88
+ def member_list(which_ones = :all)
89
+ case which_ones
90
+ when :manual
91
+ ::User.with_role(:member, self).includes(:user_profile).sort_by {|u| u.full_name.downcase}
92
+ when :automatic
93
+ if is_subscription_only?
94
+ ::User.paid_subscribers
95
+ else
96
+ self.owner ? self.owner.member_list : []
97
+ end
98
+ when :all
99
+ member_list(:manual) + member_list(:automatic)
100
+ end
101
+ end
102
+
103
+ # Can this object be read by a user
104
+ #------------------------------------------------------------------------------
105
+ def can_be_read_by?(attempting_user)
106
+ if attempting_user
107
+ self.published? && (self.is_public? || self.is_protected? || self.member?(attempting_user) || attempting_user.is_admin? ||
108
+ (self.is_subscription_only? && attempting_user.is_paid_subscriber?) )
109
+ else
110
+ self.published? && self.is_public?
111
+ end
112
+ end
113
+
114
+ # Can this object be replied to by user
115
+ #------------------------------------------------------------------------------
116
+ def can_be_replied_by?(attempting_user)
117
+ if attempting_user
118
+ self.published? && (self.is_public? || self.is_protected? || self.member?(attempting_user) || attempting_user.is_admin? ||
119
+ (self.is_subscription_only? && attempting_user.is_paid_subscriber?) )
120
+ else
121
+ false # must be logged in to make a reply
122
+ end
123
+ end
124
+ end
125
+
126
+ module ClassMethods
127
+
128
+ # Get list of available objects for user
129
+ #------------------------------------------------------------------------------
130
+ def available_to_user(user)
131
+ if user.nil?
132
+ #--- not logged in, only public
133
+ objects = self.by_public.published
134
+ elsif user.is_admin?
135
+ objects = self.all
136
+ else
137
+ #--- all public/protected, as well as private that they are a member and subscriptions
138
+ objects = self.all_public.published
139
+ objects += self.by_private.published.with_role(:member, user)
140
+ self.by_private.published.where('owner_id IS NOT NULL').each do |item|
141
+ objects << item if item.owner.member?(user)
142
+ end
143
+ objects += self.by_subscription.published if user.is_paid_subscriber?
144
+ return objects
145
+ end
146
+ end
147
+ end
148
+ end
149
+ end
150
+ end
151
+