fae-railsz 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (328) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +5 -0
  3. data/Rakefile +37 -0
  4. data/app/assets/fonts/fae/icons.eot +0 -0
  5. data/app/assets/fonts/fae/icons.svg +56 -0
  6. data/app/assets/fonts/fae/icons.ttf +0 -0
  7. data/app/assets/fonts/fae/icons.woff +0 -0
  8. data/app/assets/fonts/fae/lato-bold-webfont.eot +0 -0
  9. data/app/assets/fonts/fae/lato-bold-webfont.svg +4551 -0
  10. data/app/assets/fonts/fae/lato-bold-webfont.ttf +0 -0
  11. data/app/assets/fonts/fae/lato-bold-webfont.woff +0 -0
  12. data/app/assets/fonts/fae/lato-light-webfont.eot +0 -0
  13. data/app/assets/fonts/fae/lato-light-webfont.svg +4241 -0
  14. data/app/assets/fonts/fae/lato-light-webfont.ttf +0 -0
  15. data/app/assets/fonts/fae/lato-light-webfont.woff +0 -0
  16. data/app/assets/fonts/fae/lato-regular-webfont.eot +0 -0
  17. data/app/assets/fonts/fae/lato-regular-webfont.svg +4241 -0
  18. data/app/assets/fonts/fae/lato-regular-webfont.ttf +0 -0
  19. data/app/assets/fonts/fae/lato-regular-webfont.woff +0 -0
  20. data/app/assets/fonts/fae/selection.json +1334 -0
  21. data/app/assets/images/fae/error_bg.jpg +0 -0
  22. data/app/assets/images/fae/error_sad_face.png +0 -0
  23. data/app/assets/images/fae/icons/alert.svg +9 -0
  24. data/app/assets/images/fae/icons/arrow_down.svg +8 -0
  25. data/app/assets/images/fae/icons/arrow_left.svg +9 -0
  26. data/app/assets/images/fae/icons/arrow_right.svg +9 -0
  27. data/app/assets/images/fae/icons/arrow_stacked.svg +8 -0
  28. data/app/assets/images/fae/icons/arrow_up.svg +8 -0
  29. data/app/assets/images/fae/icons/calendar.svg +17 -0
  30. data/app/assets/images/fae/icons/check.svg +7 -0
  31. data/app/assets/images/fae/icons/checkmark.svg +8 -0
  32. data/app/assets/images/fae/icons/chevron_down.svg +7 -0
  33. data/app/assets/images/fae/icons/chevron_left.svg +10 -0
  34. data/app/assets/images/fae/icons/chevron_right.svg +10 -0
  35. data/app/assets/images/fae/icons/chevron_up.svg +7 -0
  36. data/app/assets/images/fae/icons/delete.svg +8 -0
  37. data/app/assets/images/fae/icons/delete_x.svg +8 -0
  38. data/app/assets/images/fae/icons/edit.svg +11 -0
  39. data/app/assets/images/fae/icons/handle.svg +13 -0
  40. data/app/assets/images/fae/icons/home.svg +10 -0
  41. data/app/assets/images/fae/icons/logout.svg +12 -0
  42. data/app/assets/images/fae/icons/magnifying_glass.svg +10 -0
  43. data/app/assets/images/fae/icons/menu.svg +11 -0
  44. data/app/assets/images/fae/icons/offlink.svg +25 -0
  45. data/app/assets/images/fae/icons/plus.svg +8 -0
  46. data/app/assets/images/fae/icons/pulldown.svg +11 -0
  47. data/app/assets/images/fae/icons/search.svg +11 -0
  48. data/app/assets/images/fae/icons/settings.svg +12 -0
  49. data/app/assets/images/fae/icons/sort.svg +11 -0
  50. data/app/assets/images/fae/icons/support.svg +15 -0
  51. data/app/assets/images/fae/icons/trash.svg +10 -0
  52. data/app/assets/images/fae/icons/trumbowyg.svg +1 -0
  53. data/app/assets/images/fae/icons/user.svg +13 -0
  54. data/app/assets/images/fae/icons/users.svg +19 -0
  55. data/app/assets/images/fae/icons/zoom.svg +12 -0
  56. data/app/assets/images/fae/tutorial_model_location.png +0 -0
  57. data/app/assets/images/fae/youtube_helper.jpg +0 -0
  58. data/app/assets/javascripts/fae/_modals.js +60 -0
  59. data/app/assets/javascripts/fae/_tables.js +403 -0
  60. data/app/assets/javascripts/fae/admin.js.erb +11 -0
  61. data/app/assets/javascripts/fae/application.js +63 -0
  62. data/app/assets/javascripts/fae/fae_init.js +8 -0
  63. data/app/assets/javascripts/fae/form/_ajax.js +380 -0
  64. data/app/assets/javascripts/fae/form/_cancel.js +38 -0
  65. data/app/assets/javascripts/fae/form/_filtering.js +276 -0
  66. data/app/assets/javascripts/fae/form/_form.js +60 -0
  67. data/app/assets/javascripts/fae/form/_slugger.js.erb +100 -0
  68. data/app/assets/javascripts/fae/form/_validator.js +459 -0
  69. data/app/assets/javascripts/fae/form/fae_chosen.js +44 -0
  70. data/app/assets/javascripts/fae/form/fileinputer.js +178 -0
  71. data/app/assets/javascripts/fae/form/hinter.js +111 -0
  72. data/app/assets/javascripts/fae/form/inputs/_checkbox.js +27 -0
  73. data/app/assets/javascripts/fae/form/inputs/_color.js +42 -0
  74. data/app/assets/javascripts/fae/form/inputs/_dates.js +78 -0
  75. data/app/assets/javascripts/fae/form/inputs/_select.js +162 -0
  76. data/app/assets/javascripts/fae/form/inputs/_text.js +118 -0
  77. data/app/assets/javascripts/fae/navigation/_global_search.js +184 -0
  78. data/app/assets/javascripts/fae/navigation/_language.js +89 -0
  79. data/app/assets/javascripts/fae/navigation/_navigation.js +206 -0
  80. data/app/assets/javascripts/fae/navigation/_subnav_highlighter.js +81 -0
  81. data/app/assets/javascripts/fae/navigation/sticky.js +186 -0
  82. data/app/assets/javascripts/fae/vendor/chosen.jquery.min.js +2 -0
  83. data/app/assets/javascripts/fae/vendor/frob_core_helpers.js +587 -0
  84. data/app/assets/javascripts/fae/vendor/fryr.js +437 -0
  85. data/app/assets/javascripts/fae/vendor/jqColorPicker.min.js +4 -0
  86. data/app/assets/javascripts/fae/vendor/jquery.daterangepicker.js +1292 -0
  87. data/app/assets/javascripts/fae/vendor/jquery.multi-select.js +534 -0
  88. data/app/assets/javascripts/fae/vendor/jquery.simplemodal.1.4.4.js +719 -0
  89. data/app/assets/javascripts/fae/vendor/jquery.tablesorter.js +1901 -0
  90. data/app/assets/javascripts/fae/vendor/js.cookie.js +139 -0
  91. data/app/assets/javascripts/fae/vendor/moment.min.js +7 -0
  92. data/app/assets/javascripts/fae/vendor/simplemde.min.js +13 -0
  93. data/app/assets/javascripts/fae/vendor/touch_punch.js +11 -0
  94. data/app/assets/javascripts/fae/vendor/trumbowyg.js.erb +4 -0
  95. data/app/assets/javascripts/fae/vendor/trumbowyg/plugins/upload/trumbowyg.upload.js +223 -0
  96. data/app/assets/javascripts/fae/vendor/trumbowyg/trumbowyg.js +1603 -0
  97. data/app/assets/stylesheets/fae/application.css +8 -0
  98. data/app/assets/stylesheets/fae/base.scss +82 -0
  99. data/app/assets/stylesheets/fae/globals/_fonts.scss +43 -0
  100. data/app/assets/stylesheets/fae/globals/_icons.scss +15 -0
  101. data/app/assets/stylesheets/fae/globals/_plugins.scss +51 -0
  102. data/app/assets/stylesheets/fae/globals/_tags.scss +68 -0
  103. data/app/assets/stylesheets/fae/globals/imports/_extends.scss +53 -0
  104. data/app/assets/stylesheets/fae/globals/imports/_mixins.scss +58 -0
  105. data/app/assets/stylesheets/fae/globals/imports/_variables.scss +165 -0
  106. data/app/assets/stylesheets/fae/globals/imports/finescss/_fine.scss +7 -0
  107. data/app/assets/stylesheets/fae/globals/imports/finescss/_fine_functions.scss +88 -0
  108. data/app/assets/stylesheets/fae/globals/imports/finescss/_fine_mixins.scss +280 -0
  109. data/app/assets/stylesheets/fae/globals/imports/finescss/_fine_variables.scss +30 -0
  110. data/app/assets/stylesheets/fae/globals/layout/_base.scss +48 -0
  111. data/app/assets/stylesheets/fae/globals/layout/_breadcrumbs.scss +45 -0
  112. data/app/assets/stylesheets/fae/globals/layout/_content-header.scss +99 -0
  113. data/app/assets/stylesheets/fae/globals/legacy/_pre-1.3.scss +659 -0
  114. data/app/assets/stylesheets/fae/globals/navigation/_base.scss +22 -0
  115. data/app/assets/stylesheets/fae/globals/navigation/_footer.scss +50 -0
  116. data/app/assets/stylesheets/fae/globals/navigation/_header.scss +149 -0
  117. data/app/assets/stylesheets/fae/globals/navigation/_mobilenav.scss +149 -0
  118. data/app/assets/stylesheets/fae/globals/navigation/_search.scss +76 -0
  119. data/app/assets/stylesheets/fae/globals/navigation/_sidenav.scss +142 -0
  120. data/app/assets/stylesheets/fae/globals/navigation/_utility.scss +95 -0
  121. data/app/assets/stylesheets/fae/modules/_alerts.scss +50 -0
  122. data/app/assets/stylesheets/fae/modules/_buttons.scss +62 -0
  123. data/app/assets/stylesheets/fae/modules/_modal.scss +78 -0
  124. data/app/assets/stylesheets/fae/modules/_toggles.scss +48 -0
  125. data/app/assets/stylesheets/fae/modules/forms/_asset-actions.scss +83 -0
  126. data/app/assets/stylesheets/fae/modules/forms/_base.scss +100 -0
  127. data/app/assets/stylesheets/fae/modules/forms/_checkbox.scss +87 -0
  128. data/app/assets/stylesheets/fae/modules/forms/_colorpicker.scss +57 -0
  129. data/app/assets/stylesheets/fae/modules/forms/_date.scss +335 -0
  130. data/app/assets/stylesheets/fae/modules/forms/_hints.scss +40 -0
  131. data/app/assets/stylesheets/fae/modules/forms/_label.scss +57 -0
  132. data/app/assets/stylesheets/fae/modules/forms/_radio.scss +69 -0
  133. data/app/assets/stylesheets/fae/modules/forms/_select.scss +317 -0
  134. data/app/assets/stylesheets/fae/modules/forms/_simple-mde.scss +29 -0
  135. data/app/assets/stylesheets/fae/modules/forms/_text.scss +62 -0
  136. data/app/assets/stylesheets/fae/modules/forms/_textarea.scss +16 -0
  137. data/app/assets/stylesheets/fae/modules/forms/_validation.scss +63 -0
  138. data/app/assets/stylesheets/fae/modules/tables/_actions.scss +41 -0
  139. data/app/assets/stylesheets/fae/modules/tables/_base.scss +63 -0
  140. data/app/assets/stylesheets/fae/modules/tables/_collapsible.scss +76 -0
  141. data/app/assets/stylesheets/fae/modules/tables/_filters.scss +61 -0
  142. data/app/assets/stylesheets/fae/modules/tables/_image.scss +21 -0
  143. data/app/assets/stylesheets/fae/modules/tables/_pagination.scss +34 -0
  144. data/app/assets/stylesheets/fae/modules/tables/_sorting.scss +58 -0
  145. data/app/assets/stylesheets/fae/modules/tables/_sticky.scss +9 -0
  146. data/app/assets/stylesheets/fae/modules/tables/_tooltips.scss +24 -0
  147. data/app/assets/stylesheets/fae/pages/_error.scss +35 -0
  148. data/app/assets/stylesheets/fae/pages/_help.scss +28 -0
  149. data/app/assets/stylesheets/fae/pages/_home.scss +18 -0
  150. data/app/assets/stylesheets/fae/pages/_login.scss +137 -0
  151. data/app/assets/stylesheets/fae/vendor/chosen.css +377 -0
  152. data/app/assets/stylesheets/fae/vendor/daterangepicker.css +227 -0
  153. data/app/assets/stylesheets/fae/vendor/reset.css +48 -0
  154. data/app/assets/stylesheets/fae/vendor/simplemde.min.css +7 -0
  155. data/app/assets/stylesheets/fae/vendor/trumbowyg.css +584 -0
  156. data/app/controllers/concerns/fae/application_controller_concern.rb +1 -0
  157. data/app/controllers/concerns/fae/asset_cloner.rb +46 -0
  158. data/app/controllers/concerns/fae/cloneable.rb +136 -0
  159. data/app/controllers/fae/application_controller.rb +123 -0
  160. data/app/controllers/fae/base_controller.rb +117 -0
  161. data/app/controllers/fae/files_controller.rb +26 -0
  162. data/app/controllers/fae/images_controller.rb +37 -0
  163. data/app/controllers/fae/nested_base_controller.rb +100 -0
  164. data/app/controllers/fae/options_controller.rb +29 -0
  165. data/app/controllers/fae/pages_controller.rb +44 -0
  166. data/app/controllers/fae/setup_controller.rb +54 -0
  167. data/app/controllers/fae/static_pages_controller.rb +54 -0
  168. data/app/controllers/fae/users_controller.rb +71 -0
  169. data/app/controllers/fae/utilities_controller.rb +61 -0
  170. data/app/helpers/fae/application_helper.rb +114 -0
  171. data/app/helpers/fae/fae_helper.rb +6 -0
  172. data/app/helpers/fae/form_helper.rb +240 -0
  173. data/app/helpers/fae/nested_form_helper.rb +39 -0
  174. data/app/helpers/fae/view_helper.rb +175 -0
  175. data/app/inputs/date_range_input.rb +17 -0
  176. data/app/inputs/radio_collection_input.rb +17 -0
  177. data/app/inputs/symbol_input.rb +5 -0
  178. data/app/models/concerns/fae/assets_validatable.rb +12 -0
  179. data/app/models/concerns/fae/authorization_concern.rb +12 -0
  180. data/app/models/concerns/fae/base_model_concern.rb +105 -0
  181. data/app/models/concerns/fae/change_concern.rb +1 -0
  182. data/app/models/concerns/fae/file_concern.rb +1 -0
  183. data/app/models/concerns/fae/image_concern.rb +1 -0
  184. data/app/models/concerns/fae/navigation_concern.rb +10 -0
  185. data/app/models/concerns/fae/option_concern.rb +1 -0
  186. data/app/models/concerns/fae/page_validatable.rb +26 -0
  187. data/app/models/concerns/fae/paper_trailer.rb +8 -0
  188. data/app/models/concerns/fae/role_concern.rb +1 -0
  189. data/app/models/concerns/fae/sortable.rb +51 -0
  190. data/app/models/concerns/fae/static_page_concern.rb +1 -0
  191. data/app/models/concerns/fae/text_area_concern.rb +1 -0
  192. data/app/models/concerns/fae/text_field_concern.rb +1 -0
  193. data/app/models/concerns/fae/trackable.rb +124 -0
  194. data/app/models/concerns/fae/user_concern.rb +7 -0
  195. data/app/models/fae/authorization.rb +8 -0
  196. data/app/models/fae/change.rb +53 -0
  197. data/app/models/fae/file.rb +24 -0
  198. data/app/models/fae/image.rb +33 -0
  199. data/app/models/fae/navigation.rb +132 -0
  200. data/app/models/fae/option.rb +38 -0
  201. data/app/models/fae/role.rb +18 -0
  202. data/app/models/fae/static_page.rb +109 -0
  203. data/app/models/fae/text_area.rb +14 -0
  204. data/app/models/fae/text_field.rb +14 -0
  205. data/app/models/fae/user.rb +67 -0
  206. data/app/uploaders/fae/file_uploader.rb +26 -0
  207. data/app/uploaders/fae/image_uploader.rb +28 -0
  208. data/app/validators/fae/cross_model_uniqueness_validator.rb +14 -0
  209. data/app/views/devise/confirmations/new.html.slim +13 -0
  210. data/app/views/devise/mailer/confirmation_instructions.html.slim +3 -0
  211. data/app/views/devise/mailer/reset_password_instructions.html.slim +5 -0
  212. data/app/views/devise/mailer/unlock_instructions.html.slim +4 -0
  213. data/app/views/devise/passwords/edit.html.slim +10 -0
  214. data/app/views/devise/passwords/new.html.slim +10 -0
  215. data/app/views/devise/registrations/edit.html.slim +22 -0
  216. data/app/views/devise/registrations/new.html.slim +15 -0
  217. data/app/views/devise/sessions/new.html.slim +7 -0
  218. data/app/views/devise/shared/_links.slim +25 -0
  219. data/app/views/devise/unlocks/new.html.slim +13 -0
  220. data/app/views/fae/application/_breadcrumb.html.slim +19 -0
  221. data/app/views/fae/application/_content_form.html.slim +55 -0
  222. data/app/views/fae/application/_credit.slim +6 -0
  223. data/app/views/fae/application/_file_uploader.html.slim +36 -0
  224. data/app/views/fae/application/_flash_messages.slim +2 -0
  225. data/app/views/fae/application/_global_search_results.html.slim +37 -0
  226. data/app/views/fae/application/_header.slim +50 -0
  227. data/app/views/fae/application/_markdown_helper.slim +41 -0
  228. data/app/views/fae/application/_mobilenav.slim +66 -0
  229. data/app/views/fae/application/_sidenav.slim +23 -0
  230. data/app/views/fae/application/_user_log.html.slim +36 -0
  231. data/app/views/fae/images/_image_uploader.html.slim +66 -0
  232. data/app/views/fae/options/_form.html.slim +16 -0
  233. data/app/views/fae/options/edit.html.slim +1 -0
  234. data/app/views/fae/pages/activity_log.html.slim +32 -0
  235. data/app/views/fae/pages/disabled_environment.html.slim +4 -0
  236. data/app/views/fae/pages/error404.html.slim +7 -0
  237. data/app/views/fae/pages/help.html.slim +35 -0
  238. data/app/views/fae/pages/home.html.slim +36 -0
  239. data/app/views/fae/setup/first_user.html.slim +11 -0
  240. data/app/views/fae/shared/_errors.slim +4 -0
  241. data/app/views/fae/shared/_form_header.html.slim +40 -0
  242. data/app/views/fae/shared/_index_header.html.slim +26 -0
  243. data/app/views/fae/shared/_nested_table.html.slim +49 -0
  244. data/app/views/fae/shared/_recent_changes.html.slim +22 -0
  245. data/app/views/fae/shared/_shared_nested_table.html.slim +46 -0
  246. data/app/views/fae/static_pages/index.html.slim +13 -0
  247. data/app/views/fae/users/_form.html.slim +19 -0
  248. data/app/views/fae/users/edit.html.slim +1 -0
  249. data/app/views/fae/users/index.html.slim +23 -0
  250. data/app/views/fae/users/new.html.slim +1 -0
  251. data/app/views/fae/users/settings.html.slim +1 -0
  252. data/app/views/kaminari/fae/_gap.html.slim +8 -0
  253. data/app/views/kaminari/fae/_next_page.html.slim +9 -0
  254. data/app/views/kaminari/fae/_page.html.slim +15 -0
  255. data/app/views/kaminari/fae/_paginator.html.slim +15 -0
  256. data/app/views/kaminari/fae/_prev_page.html.slim +9 -0
  257. data/app/views/layouts/devise.html.slim +29 -0
  258. data/app/views/layouts/fae/application.html.slim +23 -0
  259. data/app/views/layouts/fae/error.html.slim +11 -0
  260. data/config/deploy.rb +73 -0
  261. data/config/deploy/dev.rb +19 -0
  262. data/config/deploy/prod.rb +19 -0
  263. data/config/deploy/stage.rb +19 -0
  264. data/config/initializers/assets.rb +1 -0
  265. data/config/initializers/carrierwave.rb +3 -0
  266. data/config/initializers/devise.rb +258 -0
  267. data/config/initializers/devise_monkeypatch.rb +11 -0
  268. data/config/initializers/fae_judge.rb +3 -0
  269. data/config/initializers/inflections.rb +16 -0
  270. data/config/initializers/kaminari_config.rb +10 -0
  271. data/config/initializers/simple_form.rb +147 -0
  272. data/config/initializers/time_formats.rb +3 -0
  273. data/config/locales/devise.en.yml +59 -0
  274. data/config/locales/devise.zh-CN.yml +59 -0
  275. data/config/locales/fae.en.yml +10 -0
  276. data/config/locales/fae.zh-CN.yml +10 -0
  277. data/config/locales/simple_form.en.yml +26 -0
  278. data/config/locales/simple_form.zh-CN.yml +26 -0
  279. data/config/routes.rb +46 -0
  280. data/db/migrate/20140809222030_add_user_table.rb +49 -0
  281. data/db/migrate/20140822224029_create_fae_roles.rb +10 -0
  282. data/db/migrate/20141008180718_create_fae_images_table.rb +19 -0
  283. data/db/migrate/20141017194616_create_fae_options.rb +16 -0
  284. data/db/migrate/20141021181327_create_fae_files.rb +17 -0
  285. data/db/migrate/20141021183047_create_fae_text_areas.rb +16 -0
  286. data/db/migrate/20141021184311_create_fae_pages.rb +13 -0
  287. data/db/migrate/20141105214814_create_fae_text_fields.rb +15 -0
  288. data/db/migrate/20150930224821_create_fae_changes.rb +17 -0
  289. data/lib/fae-rails.rb +6 -0
  290. data/lib/fae/concerns/models/base.rb +8 -0
  291. data/lib/fae/engine.rb +37 -0
  292. data/lib/fae/options.rb +35 -0
  293. data/lib/fae/validation_helper_collection.rb +76 -0
  294. data/lib/fae/version.rb +3 -0
  295. data/lib/file_size_validator.rb +71 -0
  296. data/lib/generators/fae/base_generator.rb +156 -0
  297. data/lib/generators/fae/controller_generator.rb +13 -0
  298. data/lib/generators/fae/install_generator.rb +61 -0
  299. data/lib/generators/fae/model_generator.rb +11 -0
  300. data/lib/generators/fae/nested_index_scaffold_generator.rb +36 -0
  301. data/lib/generators/fae/nested_scaffold_generator.rb +51 -0
  302. data/lib/generators/fae/page_generator.rb +65 -0
  303. data/lib/generators/fae/scaffold_generator.rb +15 -0
  304. data/lib/generators/fae/templates/assets/fae.js +6 -0
  305. data/lib/generators/fae/templates/assets/fae.scss +2 -0
  306. data/lib/generators/fae/templates/controllers/nested_index_scaffold_controller.rb +81 -0
  307. data/lib/generators/fae/templates/controllers/nested_scaffold_controller.rb +13 -0
  308. data/lib/generators/fae/templates/controllers/scaffold_controller.rb +13 -0
  309. data/lib/generators/fae/templates/controllers/static_pages_controller.rb +10 -0
  310. data/lib/generators/fae/templates/initializers/fae.rb +63 -0
  311. data/lib/generators/fae/templates/initializers/fae_fine.rb +51 -0
  312. data/lib/generators/fae/templates/initializers/judge.rb +6 -0
  313. data/lib/generators/fae/templates/models/concerns/authorization_concern.rb +27 -0
  314. data/lib/generators/fae/templates/models/concerns/navigation_concern.rb +33 -0
  315. data/lib/generators/fae/templates/models/pages_model.rb +14 -0
  316. data/lib/generators/fae/templates/tasks/fae_tasks.rake +19 -0
  317. data/lib/generators/fae/templates/views/_form.html.slim +18 -0
  318. data/lib/generators/fae/templates/views/_form_index_nested.html.slim +13 -0
  319. data/lib/generators/fae/templates/views/_form_nested.html.slim +17 -0
  320. data/lib/generators/fae/templates/views/edit.html.slim +1 -0
  321. data/lib/generators/fae/templates/views/edit_nested.html.slim +3 -0
  322. data/lib/generators/fae/templates/views/index.html.slim +35 -0
  323. data/lib/generators/fae/templates/views/index_nested.html.slim +8 -0
  324. data/lib/generators/fae/templates/views/new.html.slim +1 -0
  325. data/lib/generators/fae/templates/views/new_nested.html.slim +3 -0
  326. data/lib/generators/fae/templates/views/static_page_form.html.slim +15 -0
  327. data/lib/generators/fae/templates/views/table_nested.html.slim +4 -0
  328. metadata +692 -0
@@ -0,0 +1,114 @@
1
+ module Fae
2
+ module ApplicationHelper
3
+
4
+ def form_header(name)
5
+ name = name.class.name.split('::').last unless name.is_a? String
6
+ form_title = "#{params[:action]} #{name}".titleize
7
+ form_title = form_title.singularize if params[:action] == 'edit'
8
+ content_tag :h1, form_title
9
+ end
10
+
11
+ def require_locals(local_array, local_assigns)
12
+ local_array.each do |loc|
13
+ raise "#{loc} is a required local, please define it when you render this partial" unless local_assigns[loc.to_sym].present?
14
+ end
15
+ end
16
+
17
+ def nav_active_class(klass, level, idx, parent_idx = nil)
18
+ return klass unless @fae_navigation.coordinates[level] == idx
19
+ return klass unless parent_idx.blank? || @fae_navigation.coordinates[level-1] == parent_idx
20
+ new_klass = parent_idx.blank? ? '-parent-current -open' : '-current'
21
+ new_klass += " #{klass}" if klass.present?
22
+ new_klass
23
+ end
24
+
25
+ def col_name_or_image(item, attribute)
26
+ value = item.send(attribute)
27
+ return if value.blank?
28
+ # if item is an image
29
+ if value.class.name == 'Fae::Image'
30
+ image_tag(value.asset.thumb.url) if value.asset.thumb.url.present?
31
+ # if item's attribute is an association
32
+ elsif item.class.reflections.include?(attribute)
33
+ value.try(:fae_display_field)
34
+ # if item is a date or a time adjust to timezone
35
+ elsif value.is_a?(Date) || value.is_a?(ActiveSupport::TimeWithZone)
36
+ fae_date_format(value)
37
+ elsif value.is_a?(Time)
38
+ fae_datetime_format(value)
39
+ else
40
+ # otherwise it's an attribute so display it's value
41
+ value
42
+ end
43
+ end
44
+
45
+ def fae_scope
46
+ fae.root_path.gsub('/', '')
47
+ end
48
+
49
+ def page_title
50
+ if @page_title.present?
51
+ @page_title
52
+ else
53
+ default_page_title
54
+ end
55
+ end
56
+
57
+ def body_class
58
+ @body_class.present? ? @body_class : "#{controller_name} #{action_name}"
59
+ end
60
+
61
+ def change_item_link(change)
62
+ text = "#{change.changeable_type.gsub('Fae::','')}: "
63
+ test_source_method = :data_source_exists?
64
+
65
+ if change.changeable_type.exclude?('Fae') && change.changeable_type.exclude?('Page') && !ActiveRecord::Base.connection.send(test_source_method, change.changeable_type.tableize)
66
+ return "#{change.changeable_type}: model destroyed"
67
+ else
68
+ display_text = change.try(:changeable).try(:fae_display_field)
69
+ display_text = (display_text.is_a? Integer) ? display_text.to_s : display_text
70
+ text += display_text || "##{change.changeable_id}"
71
+
72
+ begin
73
+ return link_to text, fae.edit_content_block_path(change.changeable.slug) if change.changeable_type == 'Fae::StaticPage'
74
+ parent = change.changeable.respond_to?(:fae_parent) ? change.changeable.fae_parent : nil
75
+ edit_path = edit_polymorphic_path([main_app, fae_scope, parent, change.changeable])
76
+ return link_to text, edit_path
77
+ rescue
78
+ return text
79
+ end
80
+ end
81
+ end
82
+
83
+ private
84
+
85
+ def nav_path_current?(path)
86
+ current_page?(path) || path[1..-1].classify == params[:controller].classify
87
+ end
88
+
89
+ def default_page_title
90
+ pieces = [@option.title]
91
+ pieces << page_title_piece
92
+ pieces.join ' | '
93
+ end
94
+
95
+ def page_title_piece
96
+ return @page_title_piece if @page_title_piece.present?
97
+
98
+ action = params[:action].humanize.titleize unless params[:action] == 'index'
99
+ controller = controller_title unless params[:controller] == 'fae/pages'
100
+ controller = controller.singularize if params[:action] == 'new' || params[:action] == 'edit'
101
+
102
+ "#{action} #{controller}".strip
103
+ end
104
+
105
+ def controller_title
106
+ params[:controller].gsub(/fae\/|#{fae_scope}\//, '').humanize.titleize
107
+ end
108
+
109
+ def tr_id(item)
110
+ "#{item.class.name.underscore.gsub('/', '_').pluralize}_#{item.id}"
111
+ end
112
+
113
+ end
114
+ end
@@ -0,0 +1,6 @@
1
+ # DO NOT add methods to this helper
2
+ # this empty helper is meant to be overridden in the parent app
3
+ module Fae
4
+ module FaeHelper
5
+ end
6
+ end
@@ -0,0 +1,240 @@
1
+ module Fae
2
+ module FormHelper
3
+
4
+ def fae_input(f, attribute, options={})
5
+ custom_options attribute, options
6
+ language_support f, attribute, options
7
+ label_and_hint attribute, options
8
+ list_order f, attribute, options
9
+ set_prompt f, attribute, options
10
+
11
+ add_input_class(options, 'js-markdown-editor') if options[:markdown].present?
12
+ add_input_class(options, 'js-html-editor') if options[:html].present?
13
+
14
+ set_maxlength(f, attribute, options)
15
+
16
+ f.input attribute, options
17
+ end
18
+
19
+ def fae_association(f, attribute, options={})
20
+ custom_options attribute, options
21
+ label_and_hint attribute, options
22
+ list_order f, attribute, options
23
+ set_prompt f, attribute, options if !options[:include_blank].is_a?(String)
24
+
25
+ f.association attribute, options
26
+ end
27
+
28
+ def fae_prefix(f, attribute, options={})
29
+ raise "Fae::MissingRequiredOption: fae_prefix helper method requires the 'prefix' option." if options[:prefix].blank?
30
+ symbol 'prefix', options[:prefix], options
31
+ fae_input f, attribute, options
32
+ end
33
+
34
+ def fae_suffix(f, attribute, options={})
35
+ raise "Fae::MissingRequiredOption: fae_suffix helper method requires the 'suffix' option." if options[:suffix].blank?
36
+ symbol 'suffix', options[:suffix], options
37
+ fae_input f, attribute, options
38
+ end
39
+
40
+ def fae_radio(f, attribute, options={})
41
+ options[:alignment] = 'radio_collection--horizontal' if options[:type] == 'inline'
42
+ options[:alignment] = 'radio_collection--vertical' if options[:type] == 'stacked' || options[:type].blank?
43
+ options.update(as: :radio_collection, wrapper_class: "#{options[:wrapper_class]} #{options[:alignment]}", no_label_div: true)
44
+ association_or_input f, attribute, options
45
+ end
46
+
47
+ def fae_checkbox(f, attribute, options={})
48
+ options[:type] ||= 'stacked'
49
+ options.update(as: :check_boxes, wrapper_class: "checkbox-wrapper js-checkbox-wrapper #{options[:wrapper_class]} -#{options[:type]}", no_label_div: true)
50
+ association_or_input f, attribute, options
51
+ end
52
+
53
+ def fae_pulldown(f, attribute, options={})
54
+ raise "Fae::MissingRequiredOption: fae_pulldown requires a 'collection' when using it on an ActiveRecord attribute." if !options.has_key?(:collection) && f.object.attribute_names.include?(attribute.to_s)
55
+ raise "Fae::ImproperOptionValue: The value #{options[:size]} is not a valid option for 'size'. Please use 'short' or 'long'." if options[:size].present? && ['short','long'].include?(options[:size]) == false
56
+ raise "Fae::ImproperOptionValue: The value #{options[:search]} is not a valid option for 'search'. Please use a Boolean." if options[:search].present? && !!options[:search] != options[:search]
57
+
58
+ add_input_class(options, 'small_pulldown') if options[:size] == "short"
59
+ add_input_class(options, 'select-search') if options[:search]
60
+ options.update(wrapper_class: "#{options[:wrapper_class]} select-no_search") if options[:search] == false
61
+ association_or_input f, attribute, options
62
+ end
63
+
64
+ def fae_multiselect(f, attribute, options={})
65
+ raise "Fae::'#{attribute}' must be an association of #{f.object}" if !is_association?(f, attribute)
66
+ raise "Fae::ImproperOptionValue: The value '#{options[:two_pane]}' is not a valid option for 'two_pane'. Please use a Boolean." if options[:two_pane].present? && !!options[:two_pane] != options[:two_pane]
67
+
68
+ options.update(input_class: "#{options[:input_class]} multiselect") if options[:two_pane] == true
69
+ fae_association f, attribute, options
70
+ end
71
+
72
+ def fae_datepicker(f, attribute, options={})
73
+ options.update(as: :string, wrapper_class: 'datepicker')
74
+ fae_input f, attribute, options
75
+ end
76
+
77
+ def fae_color_picker(f, attribute, options={})
78
+ options.update(
79
+ as: :string,
80
+ input_class: "js-color-picker color-picker #{'alpha-slider' unless options[:alpha] == false}",
81
+ input_html: { value: f.object.send(attribute).to_s } # value needs to be set to clear color picker
82
+ )
83
+ fae_input f, attribute, options
84
+ end
85
+
86
+ def fae_daterange(f, attr_array, options={})
87
+ raise "Fae::MissingRequiredOption: fae_daterange requires the 'label' option." if options[:label].blank?
88
+ raise "Fae::MalformedArgument: fae_daterange requires an array of two attributes as it's second argument." unless attr_array.present? && attr_array.is_a?(Array) && attr_array.length == 2
89
+ options.update(as: :date_range, start_date: attr_array.first, end_date: attr_array.second)
90
+ fae_input f, options[:label], options
91
+ end
92
+
93
+ def fae_grouped_select(f, attribute, options={})
94
+ raise "Fae::MissingRequiredOption: fae_grouped_select requires a `collection` option or `groups` and `labels` options." if !options.has_key?(:collection) && !options.has_key?(:groups) && !options.has_key?(:labels)
95
+ raise "Fae::MissingRequiredOption: fae_grouped_select required a `labels` option with a value containing an array when using the `groups` option." if options[:groups].present? && options[:labels].blank?
96
+ raise "Fae::MissingRequiredOption: fae_grouped_select required a `groups` option with a value containing an array when using the `labels` option." if options[:labels].present? && options[:groups].blank?
97
+
98
+ options[:collection] ||= group_options_for_collection(options[:labels], options[:groups])
99
+ options.update(as: :grouped_select, group_method: :last, wrapper_class: "#{options[:wrapper_class]} select")
100
+ association_or_input f, attribute, options
101
+ end
102
+
103
+ def fae_video_url(f, attribute, options={})
104
+ options[:helper_text] ||= "Please enter your YouTube video ID. The video ID is between v= and & of the video's url. This is typically 11 characters long."
105
+ options[:hint] ||= '<div class="youtube-hint"></div>'
106
+ fae_input f, attribute, options
107
+ end
108
+
109
+
110
+ private
111
+
112
+ def custom_options(attribute, options)
113
+ add_input_class(options, options[:input_class]) if options[:input_class].present?
114
+ add_input_class(options, 'slug') if attribute == :slug
115
+ options.update(wrapper_class: "#{options[:wrapper_class]} input") if options[:wrapper_class].present?
116
+ options.update(validate: true) unless options[:validate].present? && options[:validate] == false
117
+ end
118
+
119
+ def label_and_hint(attribute, options)
120
+ hint = options[:hint]
121
+
122
+ options[:helper_text] = attempt_common_helper_text(attribute) if options[:helper_text].blank?
123
+
124
+ attribute_name = options[:as].to_s == 'hidden' ? '' : attribute.to_s.titleize
125
+ label = options[:label] || attribute_name
126
+ if options[:markdown_supported].present? || options[:helper_text].present?
127
+ label += content_tag :h6, class: 'helper_text' do
128
+ concat(options[:helper_text]) if options[:helper_text].present?
129
+ concat(content_tag(:span, 'Markdown Supported', class: 'markdown-support')) if options[:markdown_supported].present?
130
+ end
131
+ end
132
+ options[:label] = label.html_safe if label.present?
133
+
134
+ options[:hint] = hint.html_safe if hint.present?
135
+ end
136
+
137
+ def is_attribute_or_association?(f, attribute)
138
+ f.object.has_attribute?(attribute) || is_association?(f, attribute)
139
+ end
140
+
141
+ def is_association?(f, attribute)
142
+ f.object.class.reflections.include?(attribute) || f.object.class.reflections.include?(attribute.to_s)
143
+ end
144
+
145
+ def association_or_input(f, attribute, options)
146
+ if is_attribute_or_association?(f, attribute)
147
+ f.object.attribute_names.include?(attribute.to_s) ? fae_input(f, attribute, options) : fae_association(f, attribute, options)
148
+ else
149
+ raise "Fae::undefined method '#{attribute}' for #{f.object}"
150
+ end
151
+ end
152
+
153
+ def symbol(type, val, options)
154
+ options[:as] = :symbol
155
+ options[:wrapper_class] = options[:wrapper_class].present? ? "#{options[:wrapper_class]} input symbol--#{type}" : "input symbol--#{type}"
156
+ options[:span_class] = "input-symbol--#{type}"
157
+ options[:span_class] += " icon-#{val}" if options[:icon].present?
158
+ options[:content_text] = val if options[:icon].blank?
159
+ end
160
+
161
+ def group_options_for_collection(labels, groups)
162
+ raise "Fae::groups and labels must be an array" if !(labels.is_a? Array) || !(groups.is_a? Array)
163
+ raise "Fae::grouped options must be arrays of equal length. label length: #{labels.length}, options_length: #{groups.length}" if labels.length != groups.length
164
+
165
+ collection = {}
166
+ labels.each_with_index { |label, i| collection[label] = groups[i] }
167
+ collection
168
+ end
169
+
170
+ def to_class(attribute)
171
+ attribute.to_s.classify.constantize
172
+ end
173
+
174
+ def add_input_class(options, class_name)
175
+ if options.key?(:input_html)
176
+ options[:input_html].merge!({class: "#{options[:input_html][:class]} #{class_name}"})
177
+ else
178
+ options[:input_html] = { class: class_name }
179
+ end
180
+ end
181
+
182
+ # sets collection to class.for_fae_index if not defined
183
+ def list_order(f, attribute, options)
184
+ if is_association?(f, attribute) && !options[:collection]
185
+ begin
186
+ options[:collection] = to_class(attribute).for_fae_index
187
+ rescue NameError
188
+ raise "Fae::MissingCollection: `#{attribute}` isn't an orderable class, define your order using the `collection` option."
189
+ end
190
+ end
191
+ end
192
+
193
+ # sets default prompt for pulldowns
194
+ def set_prompt(f, attribute, options)
195
+ options[:prompt] = 'Select One' if is_association?(f, attribute) && f.object.class.reflect_on_association(attribute).macro == :belongs_to && options[:prompt].nil? && !options[:two_pane]
196
+ end
197
+
198
+ # removes language suffix from label and adds data attr for languange nav
199
+ def language_support(f, attribute, options)
200
+ return if Fae.languages.blank?
201
+
202
+ attribute_array = attribute.to_s.split('_')
203
+ language_suffix = attribute_array.pop
204
+ return unless Fae.languages.has_key?(language_suffix.to_sym) || Fae.languages.has_key?(language_suffix)
205
+
206
+ label = attribute_array.push("(#{language_suffix})").join(' ').titleize
207
+ options[:label] = label unless options[:label].present?
208
+
209
+ if options[:wrapper_html].present?
210
+ options[:wrapper_html].deep_merge!({ data: { language: language_suffix } })
211
+ else
212
+ options[:wrapper_html] = { data: { language: language_suffix } }
213
+ end
214
+ end
215
+
216
+ def set_maxlength(f, attribute, options)
217
+ column = f.object.class.columns_hash[attribute.to_s]
218
+ if column.present? && (column.sql_type.include?('varchar') || column.sql_type == 'text')
219
+ # Rails 4.1 supports column.limit, 4.2 supports column.cast_type.limit
220
+ limit = column.try(:limit) || column.try(:cast_type).try(:limit)
221
+ if limit.present?
222
+ options[:input_html] ||= {}
223
+ options[:input_html][:maxlength] ||= limit
224
+ end
225
+ end
226
+ end
227
+
228
+ def attempt_common_helper_text(attribute)
229
+ case attribute
230
+ when :seo_title
231
+ return 'A descriptive page title of ~50-65 characters. Displayed in search engine results.'
232
+ when :seo_description
233
+ return 'A helpful page summary of 320 characters or less. Displayed in search engine results.'
234
+ else
235
+ ''
236
+ end
237
+ end
238
+
239
+ end
240
+ end
@@ -0,0 +1,39 @@
1
+ module Fae
2
+ module NestedFormHelper
3
+
4
+ def th_columns(attribute)
5
+ if (attribute.is_a?(Hash) && attribute[:title])
6
+ attribute = attribute[:title]
7
+ attribute_title = attribute
8
+ else
9
+ attribute = :modified if ['updated_at', 'modified_at'].include? attribute.to_s
10
+ attribute_title = attribute.to_s.titleize
11
+ end
12
+
13
+ th_class = '-action-wide' if [:on_production, :on_prod, :on_stage, :updated_at, :created_at, :modified].include?(attribute)
14
+ content_tag(:th, class: th_class) do attribute_title end
15
+ end
16
+
17
+ def td_columns(params)
18
+ attribute = params[:col]
19
+ attributes = params[:cols]
20
+ item = params[:item]
21
+
22
+ attribute = (attribute.is_a?(Hash) && attribute[:attr]) ? attribute[:attr] : attribute
23
+ first_attribute = (attributes.first.kind_of?(Hash) && attributes.first[:attr]) ? attributes.first[:attr] : attributes.first
24
+
25
+ if attribute == first_attribute && !params[:edit_column]
26
+ content_tag(:td) do
27
+ content_tag(:a, class: 'js-edit-link', href: self.send(params[:edit_path], item)) do
28
+ col_name_or_image(item, attribute)
29
+ end
30
+ end
31
+ elsif item.class.columns_hash[attribute.to_s].present? && item.class.columns_hash[attribute.to_s].type == :boolean
32
+ content_tag(:td, fae_toggle(item, attribute))
33
+ else
34
+ content_tag(:td, col_name_or_image(item, attribute))
35
+ end
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,175 @@
1
+ module Fae
2
+ module ViewHelper
3
+
4
+ def fae_date_format(datetime, timezone = @option.time_zone)
5
+ datetime.in_time_zone(timezone).strftime('%m/%d/%y') if is_date_or_time?(datetime)
6
+ end
7
+
8
+ def fae_datetime_format(datetime, timezone = @option.time_zone)
9
+ datetime.in_time_zone(timezone).strftime("%b %-d, %Y %l:%M%P %Z") if is_date_or_time?(datetime)
10
+ end
11
+
12
+ def fae_path
13
+ Rails.application.routes.url_helpers.fae_path[1..-1]
14
+ end
15
+
16
+ def fae_image_form(f, image_name, label: nil, alt_label: nil, caption_label: nil, show_alt: nil, show_caption: nil, required: nil, helper_text: nil, alt_helper_text: nil, caption_helper_text: nil, attached_as: nil)
17
+ render 'fae/images/image_uploader', f: f, image_name: image_name, label: label, alt_label: alt_label, caption_label: caption_label, show_alt: show_alt, show_caption: show_caption, required: required, helper_text: helper_text, alt_helper_text: alt_helper_text, caption_helper_text: caption_helper_text, attached_as: attached_as
18
+ end
19
+
20
+ def fae_file_form(f, file_name, label: nil, helper_text: nil, required: nil)
21
+ render 'fae/application/file_uploader', f: f, file_name: file_name, label: label, required: required, helper_text: helper_text
22
+ end
23
+
24
+ def fae_content_form(f, attribute, label: nil, hint: nil, helper_text: nil, markdown: nil, markdown_supported: nil, input_options: nil)
25
+ render 'fae/application/content_form', f: f, attribute: attribute, label: label, hint: hint, helper_text: helper_text, markdown: markdown, markdown_supported: markdown_supported, input_options: input_options
26
+ end
27
+
28
+ def fae_index_image(image, path = nil)
29
+ return if image.blank? || image.asset.blank? || image.asset.thumb.blank?
30
+ content_tag :div, class: 'image-mat' do
31
+ link_to_if path.present?, image_tag(image.asset.thumb.url), path
32
+ end
33
+ end
34
+
35
+ def fae_toggle(item, column)
36
+ active = item.send(column)
37
+ link_class = active ? 'slider-yes-selected' : ''
38
+ model_name = item.class.to_s.gsub('::','__').underscore.pluralize
39
+ url = fae.toggle_path(model_name, item.id.to_s, column)
40
+
41
+ link_to url, class: "slider-wrapper #{link_class}", method: :post, remote: true do
42
+ '<div class="slider-options">
43
+ <div class="slider-option slider-option-yes">Yes</div>
44
+ <div class="slider-option-selector"></div>
45
+ <div class="slider-option slider-option-no">No</div>
46
+ </div>'.html_safe
47
+ end
48
+ end
49
+
50
+ def fae_clone_button(item)
51
+ return if item.blank?
52
+ link_to "#{@index_path}?from_existing=#{item.id}", method: :post, title: 'Clone', class: 'js-tooltip table-action', data: { confirm: t('fae.clone_confirmation') } do
53
+ concat content_tag :i, nil, class: 'icon-copy'
54
+ end
55
+ end
56
+
57
+ def fae_delete_button(item, delete_path = nil, *custom_attrs)
58
+ return if item.blank?
59
+ delete_path ||= polymorphic_path([main_app, fae_scope, item.try(:fae_parent), item])
60
+ attrs = { method: :delete, title: 'Delete', class: 'js-tooltip table-action', data: { confirm: t('fae.delete_confirmation') } }
61
+ attrs.deep_merge!(custom_attrs[0]) if custom_attrs.present?
62
+ link_to delete_path, attrs do
63
+ concat content_tag :i, nil, class: 'icon-trash'
64
+ end
65
+ end
66
+
67
+ def fae_sort_id(item)
68
+ return if item.blank?
69
+ klass = item.class.name.underscore.gsub('/','__')
70
+ "#{klass}_#{item.id}"
71
+ end
72
+
73
+ def fae_filter_form(options = {}, &block)
74
+ options[:collection] ||= @items
75
+ options[:action] ||= "#{@index_path}/filter"
76
+ options[:title] ||= "Search #{@klass_humanized.pluralize.titleize}"
77
+ options[:search] = true if options[:search].nil?
78
+ options[:cookie_key] ||= false
79
+
80
+ return if options[:collection].blank?
81
+
82
+ form_hash = { class: 'js-filter-form table-filter-area' }
83
+ form_hash['data-cookie-key'] = options[:cookie_key] if options[:cookie_key].present?
84
+
85
+ filter_header = content_tag(:div, class: 'table-filter-header') do
86
+ concat content_tag :h4, options[:title]
87
+ concat filter_search_field if options[:search]
88
+ end
89
+
90
+ form_tag(options[:action], form_hash) do
91
+ concat filter_header
92
+
93
+ if block_given?
94
+ filter_group_wrapper = content_tag(:div, class: 'table-filter-group-wrapper') do
95
+ concat capture(&block)
96
+ concat content_tag(:div, content_tag(:a, 'Reset Search', class: 'js-reset-btn button -small hidden', href: '#'), class: 'table-filter-group')
97
+ end
98
+ end
99
+
100
+ concat filter_group_wrapper
101
+ # I know this `unless !` looks like it should be an `if` but it's definitely supposed to be `unless !`
102
+ concat submit_tag 'Apply Filters', class: 'hidden' unless !options[:search]
103
+ end
104
+ end
105
+
106
+ def fae_filter_select(attribute, options = {})
107
+ options[:label] ||= attribute.to_s.titleize
108
+ options[:collection] ||= default_collection_from_attribute(attribute)
109
+ options[:label_method] ||= :fae_display_field
110
+ options[:placeholder] = "All #{options[:label].pluralize}" if options[:placeholder].nil?
111
+ options[:options] ||= []
112
+ options[:grouped_by] ||= nil
113
+ options[:grouped_options] ||= []
114
+
115
+ # grouped_by takes priority over grouped_options
116
+ if options[:grouped_by].present?
117
+ select_options = filter_generate_select_group(options[:collection], options[:grouped_by], options[:label_method])
118
+ elsif options[:grouped_options].present?
119
+ select_options = grouped_options_for_select(options[:grouped_options])
120
+ else
121
+ select_options = options_from_collection_for_select(options[:collection], 'id', options[:label_method])
122
+ select_options = options_for_select(options[:options]) if options[:options].present?
123
+ end
124
+
125
+
126
+ content_tag :div, class: 'table-filter-group' do
127
+ concat label_tag "filter[#{attribute}]", options[:label]
128
+ concat select_tag "filter[#{attribute}]", select_options, prompt: options[:placeholder]
129
+ end
130
+ end
131
+
132
+ def fae_avatar(user = current_user)
133
+ hash = Digest::MD5.hexdigest(user.email.downcase)
134
+ "https://secure.gravatar.com/avatar/#{hash}?s=80&d=mm"
135
+ end
136
+
137
+ def fae_paginate(items)
138
+ content_tag :nav, class: 'pagination', data: { filter_path: "#{@index_path}/filter" } do
139
+ paginate items, theme: 'fae'
140
+ end
141
+ end
142
+
143
+ private
144
+
145
+ def filter_search_field
146
+ content_tag :div, class: 'table-filter-keyword-wrapper' do
147
+ concat text_field_tag 'filter[search]', nil, placeholder: 'Search by Keyword'
148
+ concat content_tag(:i, '', class: 'icon-search')
149
+ end
150
+ end
151
+
152
+ def filter_generate_select_group(collection, grouped_by, label_method)
153
+ labels = collection.map { |c| c.send(grouped_by).try(:fae_display_field) }.uniq
154
+ grouped_hash = {}
155
+
156
+ labels.each do |label|
157
+ values = collection.select { |c| c.send(grouped_by).try(:fae_display_field) == label }
158
+ grouped_hash[label] = values.map { |v| [v.send(label_method), v.id] }
159
+ end
160
+
161
+ grouped_options_for_select(grouped_hash)
162
+ end
163
+
164
+ def default_collection_from_attribute(attribute)
165
+ attribute.to_s.classify.constantize.for_fae_index
166
+ rescue NameError
167
+ []
168
+ end
169
+
170
+ def is_date_or_time?(datetime)
171
+ datetime.present? && ( datetime.kind_of?(Date) || datetime.kind_of?(Time) || datetime.kind_of?(ActiveSupport::TimeWithZone) )
172
+ end
173
+
174
+ end
175
+ end