tribeca_cms 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (565) hide show
  1. data/Gemfile +58 -0
  2. data/LICENSE +1 -0
  3. data/README.textile +0 -0
  4. data/app/assets/images/locomotive/background/body.png +0 -0
  5. data/app/assets/images/locomotive/datepicker/ui-widget-content-top.png +0 -0
  6. data/app/assets/images/locomotive/form/error-arrow.png +0 -0
  7. data/app/assets/images/locomotive/form/input-sep.png +0 -0
  8. data/app/assets/images/locomotive/icons/flags/de.png +0 -0
  9. data/app/assets/images/locomotive/icons/flags/en.png +0 -0
  10. data/app/assets/images/locomotive/icons/flags/es.png +0 -0
  11. data/app/assets/images/locomotive/icons/flags/et.png +0 -0
  12. data/app/assets/images/locomotive/icons/flags/fr.png +0 -0
  13. data/app/assets/images/locomotive/icons/flags/it.png +0 -0
  14. data/app/assets/images/locomotive/icons/flags/nb.png +0 -0
  15. data/app/assets/images/locomotive/icons/flags/nl.png +0 -0
  16. data/app/assets/images/locomotive/icons/flags/pl.png +0 -0
  17. data/app/assets/images/locomotive/icons/flags/pt-BR.png +0 -0
  18. data/app/assets/images/locomotive/icons/flags/ru.png +0 -0
  19. data/app/assets/images/locomotive/icons/start.png +0 -0
  20. data/app/assets/images/locomotive/list/empty.png +0 -0
  21. data/app/assets/images/locomotive/list/item-left.png +0 -0
  22. data/app/assets/images/locomotive/nocoffee.png +0 -0
  23. data/app/assets/images/locomotive/plugins/sites_picker_top_arrow.png +0 -0
  24. data/app/assets/images/locomotive/rails.png +0 -0
  25. data/app/assets/javascripts/aloha/plugins/custom/locomotive_media/css/image.css +3 -0
  26. data/app/assets/javascripts/aloha/plugins/custom/locomotive_media/img/image.gif +0 -0
  27. data/app/assets/javascripts/aloha/plugins/custom/locomotive_media/lib/locomotive_media-plugin.js +96 -0
  28. data/app/assets/javascripts/aloha/plugins/custom/locomotive_media/nls/fr/i18n.js +1 -0
  29. data/app/assets/javascripts/aloha/plugins/custom/locomotive_media/nls/i18n.js +4 -0
  30. data/app/assets/javascripts/aloha/plugins/custom/locomotive_media/package.json +1 -0
  31. data/app/assets/javascripts/locomotive.js +25 -0
  32. data/app/assets/javascripts/locomotive/aloha.js.coffee +2 -0
  33. data/app/assets/javascripts/locomotive/application.js.coffee +12 -0
  34. data/app/assets/javascripts/locomotive/inline_editor.js.coffee +22 -0
  35. data/app/assets/javascripts/locomotive/models/account.js.coffee +11 -0
  36. data/app/assets/javascripts/locomotive/models/content_asset.js.coffee +20 -0
  37. data/app/assets/javascripts/locomotive/models/content_entry.js.coffee +61 -0
  38. data/app/assets/javascripts/locomotive/models/content_type.js.coffee +26 -0
  39. data/app/assets/javascripts/locomotive/models/custom_field.js.coffee +38 -0
  40. data/app/assets/javascripts/locomotive/models/custom_field_select_option.js.coffee +16 -0
  41. data/app/assets/javascripts/locomotive/models/domain.js.coffee +3 -0
  42. data/app/assets/javascripts/locomotive/models/editable_element.js.coffee +27 -0
  43. data/app/assets/javascripts/locomotive/models/membership.js.coffee +13 -0
  44. data/app/assets/javascripts/locomotive/models/page.js.coffee +27 -0
  45. data/app/assets/javascripts/locomotive/models/site.js.coffee +34 -0
  46. data/app/assets/javascripts/locomotive/models/snippet.js.coffee +11 -0
  47. data/app/assets/javascripts/locomotive/models/theme_asset.js.coffee +11 -0
  48. data/app/assets/javascripts/locomotive/models/translation.js.coffee +5 -0
  49. data/app/assets/javascripts/locomotive/not_logged_in.js.coffee +1 -0
  50. data/app/assets/javascripts/locomotive/utils/aloha_settings.js.coffee +37 -0
  51. data/app/assets/javascripts/locomotive/utils/core_ext.js +75 -0
  52. data/app/assets/javascripts/locomotive/utils/growl.js +14 -0
  53. data/app/assets/javascripts/locomotive/utils/handlebar_helpers.js.coffee +9 -0
  54. data/app/assets/javascripts/locomotive/utils/tinymce_settings.js.coffee +48 -0
  55. data/app/assets/javascripts/locomotive/views/application_view.js.coffee +92 -0
  56. data/app/assets/javascripts/locomotive/views/content_assets/picker_item_view.js.coffee +30 -0
  57. data/app/assets/javascripts/locomotive/views/content_assets/picker_view.js.coffee +58 -0
  58. data/app/assets/javascripts/locomotive/views/content_entries/_form_view.js.coffee +144 -0
  59. data/app/assets/javascripts/locomotive/views/content_entries/_popup_form_view.js.coffee +90 -0
  60. data/app/assets/javascripts/locomotive/views/content_entries/edit_view.js.coffee +9 -0
  61. data/app/assets/javascripts/locomotive/views/content_entries/index_view.js.coffee +36 -0
  62. data/app/assets/javascripts/locomotive/views/content_entries/new_view.js.coffee +8 -0
  63. data/app/assets/javascripts/locomotive/views/content_types/_form_view.js.coffee +86 -0
  64. data/app/assets/javascripts/locomotive/views/content_types/custom_field_entry_view.js.coffee +104 -0
  65. data/app/assets/javascripts/locomotive/views/content_types/custom_fields_view.coffee +94 -0
  66. data/app/assets/javascripts/locomotive/views/content_types/edit_view.coffee +14 -0
  67. data/app/assets/javascripts/locomotive/views/content_types/new_view.js.coffee +11 -0
  68. data/app/assets/javascripts/locomotive/views/content_types/select_options_view.js.coffee +89 -0
  69. data/app/assets/javascripts/locomotive/views/current_site/edit_view.js.coffee +86 -0
  70. data/app/assets/javascripts/locomotive/views/editable_elements/control_view.js.coffee +24 -0
  71. data/app/assets/javascripts/locomotive/views/editable_elements/edit_all_view.js.coffee +83 -0
  72. data/app/assets/javascripts/locomotive/views/editable_elements/file_view.js.coffee +74 -0
  73. data/app/assets/javascripts/locomotive/views/editable_elements/long_text_view.js.coffee +36 -0
  74. data/app/assets/javascripts/locomotive/views/editable_elements/short_text_view.js.coffee +22 -0
  75. data/app/assets/javascripts/locomotive/views/inline_editor/application_view.js.coffee +124 -0
  76. data/app/assets/javascripts/locomotive/views/inline_editor/toolbar_view.js.coffee +145 -0
  77. data/app/assets/javascripts/locomotive/views/my_account/edit_view.js.coffee +24 -0
  78. data/app/assets/javascripts/locomotive/views/pages/_form_view.js.coffee +162 -0
  79. data/app/assets/javascripts/locomotive/views/pages/edit_view.js.coffee +31 -0
  80. data/app/assets/javascripts/locomotive/views/pages/index_view.js.coffee +11 -0
  81. data/app/assets/javascripts/locomotive/views/pages/list_view.js.coffee +40 -0
  82. data/app/assets/javascripts/locomotive/views/pages/new_view.js.coffee +8 -0
  83. data/app/assets/javascripts/locomotive/views/shared/asset_picker_view.js.coffee +92 -0
  84. data/app/assets/javascripts/locomotive/views/shared/fields/file_view.js.coffee +88 -0
  85. data/app/assets/javascripts/locomotive/views/shared/fields/has_many_view.js.coffee +125 -0
  86. data/app/assets/javascripts/locomotive/views/shared/fields/many_to_many_view.js.coffee +131 -0
  87. data/app/assets/javascripts/locomotive/views/shared/fields/select_view.js.coffee +83 -0
  88. data/app/assets/javascripts/locomotive/views/shared/form_view.js.coffee +138 -0
  89. data/app/assets/javascripts/locomotive/views/shared/list_item_view.js.coffee +22 -0
  90. data/app/assets/javascripts/locomotive/views/shared/list_view.js.coffee +53 -0
  91. data/app/assets/javascripts/locomotive/views/sites/domain_entry_view.js.coffee +26 -0
  92. data/app/assets/javascripts/locomotive/views/sites/domains_view.js.coffee +84 -0
  93. data/app/assets/javascripts/locomotive/views/sites/membership_entry_view.js.coffee +31 -0
  94. data/app/assets/javascripts/locomotive/views/sites/memberships_view.js.coffee +41 -0
  95. data/app/assets/javascripts/locomotive/views/sites/new_view.js.coffee +43 -0
  96. data/app/assets/javascripts/locomotive/views/snippets/_form_view.js.coffee +75 -0
  97. data/app/assets/javascripts/locomotive/views/snippets/edit_view.js.coffee +6 -0
  98. data/app/assets/javascripts/locomotive/views/snippets/list_item_view.js.coffee +8 -0
  99. data/app/assets/javascripts/locomotive/views/snippets/list_view.js.coffee +17 -0
  100. data/app/assets/javascripts/locomotive/views/snippets/new_view.js.coffee +8 -0
  101. data/app/assets/javascripts/locomotive/views/theme_assets/_form_view.js.coffee +104 -0
  102. data/app/assets/javascripts/locomotive/views/theme_assets/edit_view.js.coffee +16 -0
  103. data/app/assets/javascripts/locomotive/views/theme_assets/image_picker_view.js.coffee +48 -0
  104. data/app/assets/javascripts/locomotive/views/theme_assets/index_view.js.coffee +91 -0
  105. data/app/assets/javascripts/locomotive/views/theme_assets/list_item_view.js.coffee +8 -0
  106. data/app/assets/javascripts/locomotive/views/theme_assets/list_view.js.coffee +17 -0
  107. data/app/assets/javascripts/locomotive/views/theme_assets/new_view.js.coffee +8 -0
  108. data/app/assets/javascripts/locomotive/views/translations/_form_view.js.coffee +20 -0
  109. data/app/assets/javascripts/locomotive/views/translations/edit_view.js.coffee +6 -0
  110. data/app/assets/javascripts/locomotive/views/translations/new_view.js.coffee +8 -0
  111. data/app/assets/javascripts/tinymce/plugins/jqueryinlinepopups/editor_plugin.js +240 -0
  112. data/app/assets/javascripts/tinymce/plugins/locomotive_media/editor_plugin.js +78 -0
  113. data/app/assets/javascripts/tinymce/themes/advanced/skins/locomotive/content.css +66 -0
  114. data/app/assets/javascripts/tinymce/themes/advanced/skins/locomotive/dialog.css.scss +78 -0
  115. data/app/assets/javascripts/tinymce/themes/advanced/skins/locomotive/img/butt2.png +0 -0
  116. data/app/assets/javascripts/tinymce/themes/advanced/skins/locomotive/img/button-bg.png +0 -0
  117. data/app/assets/javascripts/tinymce/themes/advanced/skins/locomotive/img/buttons.png +0 -0
  118. data/app/assets/javascripts/tinymce/themes/advanced/skins/locomotive/img/down_arrow.gif +0 -0
  119. data/app/assets/javascripts/tinymce/themes/advanced/skins/locomotive/img/fade-butt.png +0 -0
  120. data/app/assets/javascripts/tinymce/themes/advanced/skins/locomotive/img/icons.png +0 -0
  121. data/app/assets/javascripts/tinymce/themes/advanced/skins/locomotive/img/items.gif +0 -0
  122. data/app/assets/javascripts/tinymce/themes/advanced/skins/locomotive/img/menu-arrow.png +0 -0
  123. data/app/assets/javascripts/tinymce/themes/advanced/skins/locomotive/img/menu-check.png +0 -0
  124. data/app/assets/javascripts/tinymce/themes/advanced/skins/locomotive/img/progress.gif +0 -0
  125. data/app/assets/javascripts/tinymce/themes/advanced/skins/locomotive/img/tabs.gif +0 -0
  126. data/app/assets/javascripts/tinymce/themes/advanced/skins/locomotive/img/toolbarbg.png +0 -0
  127. data/app/assets/javascripts/tinymce/themes/advanced/skins/locomotive/ui.css +1018 -0
  128. data/app/assets/stylesheets/locomotive.css +16 -0
  129. data/app/assets/stylesheets/locomotive/backoffice/_box.css.scss +157 -0
  130. data/app/assets/stylesheets/locomotive/backoffice/_buttons.css.scss +178 -0
  131. data/app/assets/stylesheets/locomotive/backoffice/application.css.scss +332 -0
  132. data/app/assets/stylesheets/locomotive/backoffice/codemirror_changes.css.scss +19 -0
  133. data/app/assets/stylesheets/locomotive/backoffice/content_assets.css.scss +130 -0
  134. data/app/assets/stylesheets/locomotive/backoffice/datepicker.css.scss +178 -0
  135. data/app/assets/stylesheets/locomotive/backoffice/dialog_changes.css.scss +141 -0
  136. data/app/assets/stylesheets/locomotive/backoffice/editable_elements.css.scss +71 -0
  137. data/app/assets/stylesheets/locomotive/backoffice/formtastic_changes.css.scss +735 -0
  138. data/app/assets/stylesheets/locomotive/backoffice/layout.css.scss +205 -0
  139. data/app/assets/stylesheets/locomotive/backoffice/menu.css +8 -0
  140. data/app/assets/stylesheets/locomotive/backoffice/menu/_colors.css.scss +125 -0
  141. data/app/assets/stylesheets/locomotive/backoffice/menu/_helpers.css.scss +6 -0
  142. data/app/assets/stylesheets/locomotive/backoffice/menu/default.css.scss +32 -0
  143. data/app/assets/stylesheets/locomotive/backoffice/menu/main.css.scss +127 -0
  144. data/app/assets/stylesheets/locomotive/backoffice/menu/sub.css.scss +276 -0
  145. data/app/assets/stylesheets/locomotive/backoffice/sites_picker.css.scss +12 -0
  146. data/app/assets/stylesheets/locomotive/inline_editor.css +13 -0
  147. data/app/assets/stylesheets/locomotive/inline_editor/_buttons.css.scss +60 -0
  148. data/app/assets/stylesheets/locomotive/inline_editor/layout.css.scss +22 -0
  149. data/app/assets/stylesheets/locomotive/inline_editor/toolbar.css.scss +114 -0
  150. data/app/assets/stylesheets/locomotive/not_logged_in.css +8 -0
  151. data/app/assets/stylesheets/locomotive/not_logged_in/installation.css.scss +62 -0
  152. data/app/assets/stylesheets/locomotive/not_logged_in/layout.css.scss +185 -0
  153. data/app/assets/stylesheets/locomotive/shared/_helpers.css.scss +150 -0
  154. data/app/assets/stylesheets/locomotive/shared/_picker.css.scss +73 -0
  155. data/app/assets/stylesheets/locomotive/shared/common.css.scss +34 -0
  156. data/app/assets/stylesheets/locomotive/shared/content_locale_picker.css.scss +80 -0
  157. data/app/assets/stylesheets/locomotive/shared/growl.css.scss +29 -0
  158. data/app/cells/locomotive/content_locale_picker/show.html.haml +7 -0
  159. data/app/cells/locomotive/content_locale_picker_cell.rb +21 -0
  160. data/app/cells/locomotive/global_actions/show.html.haml +12 -0
  161. data/app/cells/locomotive/global_actions_cell.rb +36 -0
  162. data/app/cells/locomotive/main_menu/show.html.haml +13 -0
  163. data/app/cells/locomotive/main_menu_cell.rb +12 -0
  164. data/app/cells/locomotive/menu/show.html.haml +1 -0
  165. data/app/cells/locomotive/menu_cell.rb +102 -0
  166. data/app/cells/locomotive/settings_menu_cell.rb +14 -0
  167. data/app/cells/locomotive/sub_menu/show.html.haml +4 -0
  168. data/app/cells/locomotive/sub_menu_cell.rb +13 -0
  169. data/app/controllers/locomotive/accounts_controller.rb +18 -0
  170. data/app/controllers/locomotive/api/accounts_controller.rb +79 -0
  171. data/app/controllers/locomotive/api/base_controller.rb +50 -0
  172. data/app/controllers/locomotive/api/content_assets_controller.rb +39 -0
  173. data/app/controllers/locomotive/api/content_entries_controller.rb +45 -0
  174. data/app/controllers/locomotive/api/content_types_controller.rb +39 -0
  175. data/app/controllers/locomotive/api/current_site_controller.rb +58 -0
  176. data/app/controllers/locomotive/api/documentation_controller.rb +15 -0
  177. data/app/controllers/locomotive/api/memberships_controller.rb +97 -0
  178. data/app/controllers/locomotive/api/my_account_controller.rb +35 -0
  179. data/app/controllers/locomotive/api/pages_controller.rb +41 -0
  180. data/app/controllers/locomotive/api/sites_controller.rb +93 -0
  181. data/app/controllers/locomotive/api/snippets_controller.rb +40 -0
  182. data/app/controllers/locomotive/api/theme_assets_controller.rb +39 -0
  183. data/app/controllers/locomotive/api/tokens_controller.rb +54 -0
  184. data/app/controllers/locomotive/api/translations_controller.rb +31 -0
  185. data/app/controllers/locomotive/base_controller.rb +61 -0
  186. data/app/controllers/locomotive/content_assets_controller.rb +23 -0
  187. data/app/controllers/locomotive/content_entries_controller.rb +71 -0
  188. data/app/controllers/locomotive/content_types_controller.rb +40 -0
  189. data/app/controllers/locomotive/current_site_controller.rb +52 -0
  190. data/app/controllers/locomotive/installation_controller.rb +72 -0
  191. data/app/controllers/locomotive/memberships_controller.rb +29 -0
  192. data/app/controllers/locomotive/my_account_controller.rb +24 -0
  193. data/app/controllers/locomotive/pages_controller.rb +63 -0
  194. data/app/controllers/locomotive/passwords_controller.rb +19 -0
  195. data/app/controllers/locomotive/public/base_controller.rb +22 -0
  196. data/app/controllers/locomotive/public/content_entries_controller.rb +55 -0
  197. data/app/controllers/locomotive/public/pages_controller.rb +50 -0
  198. data/app/controllers/locomotive/public/robots_controller.rb +16 -0
  199. data/app/controllers/locomotive/public/sitemaps_controller.rb +14 -0
  200. data/app/controllers/locomotive/sessions_controller.rb +29 -0
  201. data/app/controllers/locomotive/sites_controller.rb +33 -0
  202. data/app/controllers/locomotive/snippets_controller.rb +47 -0
  203. data/app/controllers/locomotive/theme_assets_controller.rb +52 -0
  204. data/app/controllers/locomotive/translations_controller.rb +32 -0
  205. data/app/helpers/locomotive/accounts_helper.rb +13 -0
  206. data/app/helpers/locomotive/base_helper.rb +182 -0
  207. data/app/helpers/locomotive/content_entries_helper.rb +15 -0
  208. data/app/helpers/locomotive/content_types_helper.rb +72 -0
  209. data/app/helpers/locomotive/custom_fields_helper.rb +70 -0
  210. data/app/helpers/locomotive/installation_helper.rb +9 -0
  211. data/app/helpers/locomotive/pages_helper.rb +95 -0
  212. data/app/helpers/locomotive/sites_helper.rb +15 -0
  213. data/app/helpers/locomotive/snippets_helper.rb +20 -0
  214. data/app/helpers/locomotive/theme_assets_helper.rb +30 -0
  215. data/app/helpers/locomotive/translations_helper.rb +19 -0
  216. data/app/inputs/locomotive/code_input.rb +51 -0
  217. data/app/inputs/locomotive/empty_input.rb +35 -0
  218. data/app/inputs/locomotive/file_input.rb +45 -0
  219. data/app/inputs/locomotive/locale_input.rb +40 -0
  220. data/app/inputs/locomotive/locales_input.rb +60 -0
  221. data/app/inputs/locomotive/rte_input.rb +13 -0
  222. data/app/inputs/locomotive/small_code_input.rb +22 -0
  223. data/app/inputs/locomotive/subdomain_input.rb +22 -0
  224. data/app/inputs/locomotive/toggle_input.rb +13 -0
  225. data/app/mailers/locomotive/devise_mailer.rb +10 -0
  226. data/app/mailers/locomotive/notifications.rb +15 -0
  227. data/app/models/locomotive/ability.rb +89 -0
  228. data/app/models/locomotive/account.rb +117 -0
  229. data/app/models/locomotive/content_asset.rb +40 -0
  230. data/app/models/locomotive/content_entry.rb +197 -0
  231. data/app/models/locomotive/content_type.rb +224 -0
  232. data/app/models/locomotive/editable_control.rb +52 -0
  233. data/app/models/locomotive/editable_element.rb +122 -0
  234. data/app/models/locomotive/editable_file.rb +85 -0
  235. data/app/models/locomotive/editable_long_text.rb +5 -0
  236. data/app/models/locomotive/editable_short_text.rb +66 -0
  237. data/app/models/locomotive/extensions/asset/types.rb +31 -0
  238. data/app/models/locomotive/extensions/asset/vignette.rb +19 -0
  239. data/app/models/locomotive/extensions/content_type/default_values.rb +57 -0
  240. data/app/models/locomotive/extensions/content_type/item_template.rb +49 -0
  241. data/app/models/locomotive/extensions/content_type/sync.rb +62 -0
  242. data/app/models/locomotive/extensions/page/editable_elements.rb +105 -0
  243. data/app/models/locomotive/extensions/page/listed.rb +18 -0
  244. data/app/models/locomotive/extensions/page/parse.rb +125 -0
  245. data/app/models/locomotive/extensions/page/redirect.rb +25 -0
  246. data/app/models/locomotive/extensions/page/render.rb +93 -0
  247. data/app/models/locomotive/extensions/page/templatized.rb +163 -0
  248. data/app/models/locomotive/extensions/page/tree.rb +133 -0
  249. data/app/models/locomotive/extensions/shared/seo.rb +16 -0
  250. data/app/models/locomotive/extensions/site/first_installation.rb +20 -0
  251. data/app/models/locomotive/extensions/site/locales.rb +112 -0
  252. data/app/models/locomotive/extensions/site/subdomain_domains.rb +91 -0
  253. data/app/models/locomotive/membership.rb +75 -0
  254. data/app/models/locomotive/page.rb +130 -0
  255. data/app/models/locomotive/site.rb +79 -0
  256. data/app/models/locomotive/snippet.rb +70 -0
  257. data/app/models/locomotive/theme_asset.rb +175 -0
  258. data/app/models/locomotive/translation.rb +32 -0
  259. data/app/presenters/locomotive/account_presenter.rb +19 -0
  260. data/app/presenters/locomotive/base_presenter.rb +99 -0
  261. data/app/presenters/locomotive/content_asset_presenter.rb +43 -0
  262. data/app/presenters/locomotive/content_entry_presenter.rb +217 -0
  263. data/app/presenters/locomotive/content_field_presenter.rb +71 -0
  264. data/app/presenters/locomotive/content_type_presenter.rb +68 -0
  265. data/app/presenters/locomotive/editable_control_presenter.rb +19 -0
  266. data/app/presenters/locomotive/editable_element_presenter.rb +40 -0
  267. data/app/presenters/locomotive/editable_file_presenter.rb +29 -0
  268. data/app/presenters/locomotive/editable_long_text_presenter.rb +5 -0
  269. data/app/presenters/locomotive/editable_short_text_presenter.rb +27 -0
  270. data/app/presenters/locomotive/membership_presenter.rb +36 -0
  271. data/app/presenters/locomotive/page_presenter.rb +58 -0
  272. data/app/presenters/locomotive/site_presenter.rb +36 -0
  273. data/app/presenters/locomotive/snippet_presenter.rb +22 -0
  274. data/app/presenters/locomotive/theme_asset_presenter.rb +61 -0
  275. data/app/presenters/locomotive/translation_presenter.rb +9 -0
  276. data/app/uploaders/locomotive/content_asset_uploader.rb +13 -0
  277. data/app/uploaders/locomotive/editable_file_uploader.rb +15 -0
  278. data/app/uploaders/locomotive/theme_asset_uploader.rb +28 -0
  279. data/app/views/locomotive/accounts/new.html.haml +21 -0
  280. data/app/views/locomotive/content_assets/_asset.html.haml +5 -0
  281. data/app/views/locomotive/content_assets/_picker.html.haml +33 -0
  282. data/app/views/locomotive/content_entries/_form.html.haml +22 -0
  283. data/app/views/locomotive/content_entries/_list.html.haml +18 -0
  284. data/app/views/locomotive/content_entries/edit.html.haml +21 -0
  285. data/app/views/locomotive/content_entries/index.html.haml +32 -0
  286. data/app/views/locomotive/content_entries/new.html.haml +19 -0
  287. data/app/views/locomotive/content_types/_form.html.haml +39 -0
  288. data/app/views/locomotive/content_types/edit.html.haml +19 -0
  289. data/app/views/locomotive/content_types/new.html.haml +15 -0
  290. data/app/views/locomotive/current_site/_form.html.haml +36 -0
  291. data/app/views/locomotive/current_site/edit.html.haml +19 -0
  292. data/app/views/locomotive/custom_fields/_form.html.haml +61 -0
  293. data/app/views/locomotive/custom_fields/_select_templates.html.haml +16 -0
  294. data/app/views/locomotive/custom_fields/types/_belongs_to.html.haml +5 -0
  295. data/app/views/locomotive/custom_fields/types/_boolean.html.haml +4 -0
  296. data/app/views/locomotive/custom_fields/types/_date.html.haml +5 -0
  297. data/app/views/locomotive/custom_fields/types/_file.html.haml +4 -0
  298. data/app/views/locomotive/custom_fields/types/_has_many.html.haml +70 -0
  299. data/app/views/locomotive/custom_fields/types/_many_to_many.html.haml +41 -0
  300. data/app/views/locomotive/custom_fields/types/_select.html.haml +34 -0
  301. data/app/views/locomotive/custom_fields/types/_string.html.haml +4 -0
  302. data/app/views/locomotive/custom_fields/types/_text.html.haml +5 -0
  303. data/app/views/locomotive/devise_mailer/reset_password_instructions.html.haml +12 -0
  304. data/app/views/locomotive/errors/404.html.haml +7 -0
  305. data/app/views/locomotive/errors/500.html.haml +7 -0
  306. data/app/views/locomotive/errors/no_page.html.haml +1 -0
  307. data/app/views/locomotive/errors/no_site.html.haml +1 -0
  308. data/app/views/locomotive/installation/step_1.html.haml +23 -0
  309. data/app/views/locomotive/installation/step_2.html.haml +24 -0
  310. data/app/views/locomotive/layouts/application.html.haml +34 -0
  311. data/app/views/locomotive/layouts/error.html.haml +1 -0
  312. data/app/views/locomotive/layouts/not_logged_in.html.haml +18 -0
  313. data/app/views/locomotive/memberships/new.html.haml +14 -0
  314. data/app/views/locomotive/my_account/edit.html.haml +40 -0
  315. data/app/views/locomotive/notifications/new_content_entry.html.haml +29 -0
  316. data/app/views/locomotive/pages/_editable_elements.html.haml +64 -0
  317. data/app/views/locomotive/pages/_form.html.haml +61 -0
  318. data/app/views/locomotive/pages/_page.html.haml +42 -0
  319. data/app/views/locomotive/pages/edit.html.haml +18 -0
  320. data/app/views/locomotive/pages/index.html.haml +19 -0
  321. data/app/views/locomotive/pages/new.html.haml +15 -0
  322. data/app/views/locomotive/passwords/edit.html.haml +18 -0
  323. data/app/views/locomotive/passwords/new.html.haml +17 -0
  324. data/app/views/locomotive/public/pages/show_toolbar.html.haml +64 -0
  325. data/app/views/locomotive/public/sitemaps/show.xml.builder +29 -0
  326. data/app/views/locomotive/sessions/new.html.haml +17 -0
  327. data/app/views/locomotive/shared/_footer.html.haml +1 -0
  328. data/app/views/locomotive/shared/_form_actions.html.haml +14 -0
  329. data/app/views/locomotive/shared/_head.html.haml +38 -0
  330. data/app/views/locomotive/shared/_header.html.haml +10 -0
  331. data/app/views/locomotive/shared/_locale_picker_link.html.haml +6 -0
  332. data/app/views/locomotive/shared/_main_app_head.html.haml +1 -0
  333. data/app/views/locomotive/shared/_site_picker.html.haml +10 -0
  334. data/app/views/locomotive/shared/actions/_contents.html.haml +7 -0
  335. data/app/views/locomotive/shared/menu/_contents.html.haml +51 -0
  336. data/app/views/locomotive/sites/_domains.html.haml +22 -0
  337. data/app/views/locomotive/sites/_form.html.haml +12 -0
  338. data/app/views/locomotive/sites/_memberships.html.haml +27 -0
  339. data/app/views/locomotive/sites/new.html.haml +12 -0
  340. data/app/views/locomotive/snippets/_form.html.haml +13 -0
  341. data/app/views/locomotive/snippets/_snippet.html.haml +8 -0
  342. data/app/views/locomotive/snippets/edit.html.haml +18 -0
  343. data/app/views/locomotive/snippets/new.html.haml +15 -0
  344. data/app/views/locomotive/theme_assets/_asset.html.haml +11 -0
  345. data/app/views/locomotive/theme_assets/_form.html.haml +35 -0
  346. data/app/views/locomotive/theme_assets/_list.html.haml +7 -0
  347. data/app/views/locomotive/theme_assets/_picker.html.haml +25 -0
  348. data/app/views/locomotive/theme_assets/edit.html.haml +21 -0
  349. data/app/views/locomotive/theme_assets/index.html.haml +50 -0
  350. data/app/views/locomotive/theme_assets/new.html.haml +12 -0
  351. data/app/views/locomotive/translations/_form.html.haml +12 -0
  352. data/app/views/locomotive/translations/edit.html.haml +15 -0
  353. data/app/views/locomotive/translations/index.html.haml +26 -0
  354. data/app/views/locomotive/translations/new.html.haml +12 -0
  355. data/config/cucumber.yml +8 -0
  356. data/config/initializers/deny_phantomjs_ttf.rb +29 -0
  357. data/config/initializers/devise.rb +15 -0
  358. data/config/initializers/formtastic.rb +4 -0
  359. data/config/initializers/haml.rb +2 -0
  360. data/config/initializers/locomotive_loaded_first.rb +19 -0
  361. data/config/locales/admin_ui.de.yml +316 -0
  362. data/config/locales/admin_ui.en.yml +332 -0
  363. data/config/locales/admin_ui.es.yml +296 -0
  364. data/config/locales/admin_ui.et.yml +315 -0
  365. data/config/locales/admin_ui.fr.yml +326 -0
  366. data/config/locales/admin_ui.it.yml +295 -0
  367. data/config/locales/admin_ui.nb.yml +314 -0
  368. data/config/locales/admin_ui.nl.yml +279 -0
  369. data/config/locales/admin_ui.pl.yml +319 -0
  370. data/config/locales/admin_ui.pt-BR.yml +274 -0
  371. data/config/locales/admin_ui.ru.yml +313 -0
  372. data/config/locales/carrierwave.de.yml +4 -0
  373. data/config/locales/carrierwave.en.yml +4 -0
  374. data/config/locales/carrierwave.es.yml +4 -0
  375. data/config/locales/carrierwave.et.yml +4 -0
  376. data/config/locales/carrierwave.fr.yml +4 -0
  377. data/config/locales/carrierwave.it.yml +4 -0
  378. data/config/locales/carrierwave.nb.yml +4 -0
  379. data/config/locales/carrierwave.nl.yml +4 -0
  380. data/config/locales/carrierwave.pl.yml +4 -0
  381. data/config/locales/carrierwave.pt-BR.yml +4 -0
  382. data/config/locales/carrierwave.ru.yml +4 -0
  383. data/config/locales/default.de.yml +244 -0
  384. data/config/locales/default.en.yml +43 -0
  385. data/config/locales/default.es.yml +216 -0
  386. data/config/locales/default.et.yml +240 -0
  387. data/config/locales/default.fr.yml +224 -0
  388. data/config/locales/default.it.yml +243 -0
  389. data/config/locales/default.nb.yml +313 -0
  390. data/config/locales/default.nl.yml +170 -0
  391. data/config/locales/default.pl.yml +317 -0
  392. data/config/locales/default.pt-BR.yml +211 -0
  393. data/config/locales/default.ru.yml +279 -0
  394. data/config/locales/devise.de.yml +62 -0
  395. data/config/locales/devise.en.yml +63 -0
  396. data/config/locales/devise.es.yml +63 -0
  397. data/config/locales/devise.et.yml +64 -0
  398. data/config/locales/devise.fr.yml +67 -0
  399. data/config/locales/devise.it.yml +63 -0
  400. data/config/locales/devise.nb.yml +63 -0
  401. data/config/locales/devise.nl.yml +63 -0
  402. data/config/locales/devise.pl.yml +63 -0
  403. data/config/locales/devise.pt-BR.yml +61 -0
  404. data/config/locales/devise.ru.yml +63 -0
  405. data/config/locales/flash.de.yml +106 -0
  406. data/config/locales/flash.en.yml +115 -0
  407. data/config/locales/flash.es.yml +106 -0
  408. data/config/locales/flash.et.yml +106 -0
  409. data/config/locales/flash.fr.yml +106 -0
  410. data/config/locales/flash.it.yml +106 -0
  411. data/config/locales/flash.nb.yml +106 -0
  412. data/config/locales/flash.nl.yml +106 -0
  413. data/config/locales/flash.pl.yml +106 -0
  414. data/config/locales/flash.pt-BR.yml +106 -0
  415. data/config/locales/flash.ru.yml +106 -0
  416. data/config/locales/formtastic.de.yml +97 -0
  417. data/config/locales/formtastic.en.yml +105 -0
  418. data/config/locales/formtastic.es.yml +84 -0
  419. data/config/locales/formtastic.et.yml +103 -0
  420. data/config/locales/formtastic.fr.yml +94 -0
  421. data/config/locales/formtastic.it.yml +99 -0
  422. data/config/locales/formtastic.nb.yml +103 -0
  423. data/config/locales/formtastic.nl.yml +85 -0
  424. data/config/locales/formtastic.pl.yml +105 -0
  425. data/config/locales/formtastic.pt-BR.yml +70 -0
  426. data/config/locales/formtastic.ru.yml +103 -0
  427. data/config/routes.rb +116 -0
  428. data/lib/generators/locomotive/install/install_generator.rb +35 -0
  429. data/lib/generators/locomotive/install/templates/README +26 -0
  430. data/lib/generators/locomotive/install/templates/carrierwave.rb +28 -0
  431. data/lib/generators/locomotive/install/templates/dragonfly.rb +22 -0
  432. data/lib/generators/locomotive/install/templates/locomotive.rb +69 -0
  433. data/lib/generators/locomotive/install/templates/mongoid.yml +34 -0
  434. data/lib/locomotive.rb +136 -0
  435. data/lib/locomotive/action_controller.rb +5 -0
  436. data/lib/locomotive/action_controller/locale_helpers.rb +61 -0
  437. data/lib/locomotive/action_controller/public_responder.rb +17 -0
  438. data/lib/locomotive/action_controller/responder.rb +78 -0
  439. data/lib/locomotive/action_controller/section_helpers.rb +29 -0
  440. data/lib/locomotive/action_controller/url_helpers.rb +38 -0
  441. data/lib/locomotive/carrierwave.rb +10 -0
  442. data/lib/locomotive/carrierwave/asset.rb +72 -0
  443. data/lib/locomotive/carrierwave/base.rb +15 -0
  444. data/lib/locomotive/carrierwave/patches.rb +32 -0
  445. data/lib/locomotive/configuration.rb +122 -0
  446. data/lib/locomotive/core_ext.rb +64 -0
  447. data/lib/locomotive/custom_fields.rb +66 -0
  448. data/lib/locomotive/dependencies.rb +30 -0
  449. data/lib/locomotive/devise.rb +1 -0
  450. data/lib/locomotive/dragonfly.rb +38 -0
  451. data/lib/locomotive/engine.rb +37 -0
  452. data/lib/locomotive/formtastic.rb +13 -0
  453. data/lib/locomotive/haml.rb +1 -0
  454. data/lib/locomotive/httparty.rb +2 -0
  455. data/lib/locomotive/httparty/patches.rb +18 -0
  456. data/lib/locomotive/httparty/webservice.rb +42 -0
  457. data/lib/locomotive/kaminari.rb +35 -0
  458. data/lib/locomotive/liquid.rb +7 -0
  459. data/lib/locomotive/liquid/drops/base.rb +42 -0
  460. data/lib/locomotive/liquid/drops/content_entry.rb +76 -0
  461. data/lib/locomotive/liquid/drops/content_types.rb +50 -0
  462. data/lib/locomotive/liquid/drops/current_user.rb +21 -0
  463. data/lib/locomotive/liquid/drops/page.rb +55 -0
  464. data/lib/locomotive/liquid/drops/proxy_collection.rb +56 -0
  465. data/lib/locomotive/liquid/drops/site.rb +19 -0
  466. data/lib/locomotive/liquid/drops/uploader.rb +15 -0
  467. data/lib/locomotive/liquid/errors.rb +7 -0
  468. data/lib/locomotive/liquid/filters/base.rb +47 -0
  469. data/lib/locomotive/liquid/filters/date.rb +54 -0
  470. data/lib/locomotive/liquid/filters/html.rb +115 -0
  471. data/lib/locomotive/liquid/filters/misc.rb +65 -0
  472. data/lib/locomotive/liquid/filters/resize.rb +16 -0
  473. data/lib/locomotive/liquid/filters/text.rb +45 -0
  474. data/lib/locomotive/liquid/filters/translate.rb +16 -0
  475. data/lib/locomotive/liquid/patches.rb +21 -0
  476. data/lib/locomotive/liquid/tags/consume.rb +67 -0
  477. data/lib/locomotive/liquid/tags/csrf.rb +40 -0
  478. data/lib/locomotive/liquid/tags/editable.rb +5 -0
  479. data/lib/locomotive/liquid/tags/editable/base.rb +88 -0
  480. data/lib/locomotive/liquid/tags/editable/control.rb +31 -0
  481. data/lib/locomotive/liquid/tags/editable/file.rb +39 -0
  482. data/lib/locomotive/liquid/tags/editable/long_text.rb +33 -0
  483. data/lib/locomotive/liquid/tags/editable/short_text.rb +41 -0
  484. data/lib/locomotive/liquid/tags/extends.rb +47 -0
  485. data/lib/locomotive/liquid/tags/google_analytics.rb +39 -0
  486. data/lib/locomotive/liquid/tags/inherited_block.rb +31 -0
  487. data/lib/locomotive/liquid/tags/inline_editor.rb +40 -0
  488. data/lib/locomotive/liquid/tags/locale_switcher.rb +83 -0
  489. data/lib/locomotive/liquid/tags/nav.rb +155 -0
  490. data/lib/locomotive/liquid/tags/paginate.rb +111 -0
  491. data/lib/locomotive/liquid/tags/seo.rb +72 -0
  492. data/lib/locomotive/liquid/tags/snippet.rb +75 -0
  493. data/lib/locomotive/liquid/tags/with_scope.rb +47 -0
  494. data/lib/locomotive/logger.rb +11 -0
  495. data/lib/locomotive/middlewares.rb +4 -0
  496. data/lib/locomotive/middlewares/cache.rb +27 -0
  497. data/lib/locomotive/middlewares/fonts.rb +42 -0
  498. data/lib/locomotive/middlewares/inline_editor.rb +36 -0
  499. data/lib/locomotive/middlewares/seo_trailing_slash.rb +24 -0
  500. data/lib/locomotive/misc/api_documentation.rb +96 -0
  501. data/lib/locomotive/misc/api_documentation/bootstrap.html.haml +119 -0
  502. data/lib/locomotive/mongoid.rb +4 -0
  503. data/lib/locomotive/mongoid/document.rb +19 -0
  504. data/lib/locomotive/mongoid/liquid.rb +39 -0
  505. data/lib/locomotive/mongoid/patches.rb +106 -0
  506. data/lib/locomotive/mongoid/presenter.rb +73 -0
  507. data/lib/locomotive/presentable.rb +212 -0
  508. data/lib/locomotive/rails.rb +1 -0
  509. data/lib/locomotive/rails/action_view.rb +9 -0
  510. data/lib/locomotive/regexps.rb +11 -0
  511. data/lib/locomotive/render.rb +177 -0
  512. data/lib/locomotive/routing.rb +2 -0
  513. data/lib/locomotive/routing/default_constraint.rb +42 -0
  514. data/lib/locomotive/routing/site_dispatcher.rb +54 -0
  515. data/lib/locomotive/session_store.rb +64 -0
  516. data/lib/locomotive/version.rb +3 -0
  517. data/lib/locomotive_cms.rb +1 -0
  518. data/lib/tasks/cucumber.rake +66 -0
  519. data/lib/tasks/locomotive.rake +220 -0
  520. data/public/favicon.ico +0 -0
  521. data/vendor/assets/fonts/locomotive/fontawesome-webfont.eot +0 -0
  522. data/vendor/assets/fonts/locomotive/fontawesome-webfont.svg +255 -0
  523. data/vendor/assets/fonts/locomotive/fontawesome-webfont.ttf +0 -0
  524. data/vendor/assets/fonts/locomotive/fontawesome-webfont.woff +0 -0
  525. data/vendor/assets/javascripts/locomotive/ICanHandlebarz.js +88 -0
  526. data/vendor/assets/javascripts/locomotive/backbone.modelbinding.js +565 -0
  527. data/vendor/assets/javascripts/locomotive/backbone.sync.js +113 -0
  528. data/vendor/assets/javascripts/locomotive/cmd.js +31 -0
  529. data/vendor/assets/javascripts/locomotive/cookies.js +96 -0
  530. data/vendor/assets/javascripts/locomotive/datepicker_i18n.js.erb +28 -0
  531. data/vendor/assets/javascripts/locomotive/editable_field.js +50 -0
  532. data/vendor/assets/javascripts/locomotive/form_submit_notification.js +39 -0
  533. data/vendor/assets/javascripts/locomotive/growl.js +143 -0
  534. data/vendor/assets/javascripts/locomotive/handlebars.js +1493 -0
  535. data/vendor/assets/javascripts/locomotive/liquid_mode.js +42 -0
  536. data/vendor/assets/javascripts/locomotive/menu_toggler.js +37 -0
  537. data/vendor/assets/javascripts/locomotive/resize.js +9 -0
  538. data/vendor/assets/javascripts/locomotive/slugify.js +31 -0
  539. data/vendor/assets/javascripts/locomotive/smartupdater.js +296 -0
  540. data/vendor/assets/javascripts/locomotive/subscribe.js +367 -0
  541. data/vendor/assets/javascripts/locomotive/toggle.js +143 -0
  542. data/vendor/assets/javascripts/locomotive/vendor.js +1 -0
  543. data/vendor/assets/stylesheets/locomotive/blueprint/ie.css +26 -0
  544. data/vendor/assets/stylesheets/locomotive/blueprint/print.css +30 -0
  545. data/vendor/assets/stylesheets/locomotive/blueprint/screen.css +253 -0
  546. data/vendor/assets/stylesheets/locomotive/font-awesome.scss +329 -0
  547. data/vendor/assets/stylesheets/locomotive/jquery.css +3 -0
  548. data/vendor/assets/stylesheets/locomotive/jquery/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  549. data/vendor/assets/stylesheets/locomotive/jquery/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  550. data/vendor/assets/stylesheets/locomotive/jquery/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  551. data/vendor/assets/stylesheets/locomotive/jquery/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  552. data/vendor/assets/stylesheets/locomotive/jquery/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  553. data/vendor/assets/stylesheets/locomotive/jquery/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  554. data/vendor/assets/stylesheets/locomotive/jquery/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  555. data/vendor/assets/stylesheets/locomotive/jquery/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  556. data/vendor/assets/stylesheets/locomotive/jquery/images/ui-icons_222222_256x240.png +0 -0
  557. data/vendor/assets/stylesheets/locomotive/jquery/images/ui-icons_2e83ff_256x240.png +0 -0
  558. data/vendor/assets/stylesheets/locomotive/jquery/images/ui-icons_454545_256x240.png +0 -0
  559. data/vendor/assets/stylesheets/locomotive/jquery/images/ui-icons_888888_256x240.png +0 -0
  560. data/vendor/assets/stylesheets/locomotive/jquery/images/ui-icons_cd0a0a_256x240.png +0 -0
  561. data/vendor/assets/stylesheets/locomotive/jquery/images/ui-icons_ffffff_256x240.png +0 -0
  562. data/vendor/assets/stylesheets/locomotive/jquery/ui.css +406 -0
  563. data/vendor/assets/stylesheets/locomotive/liquid_mode.css +7 -0
  564. data/vendor/assets/stylesheets/locomotive/toggle.css.scss +75 -0
  565. metadata +1171 -0
@@ -0,0 +1,117 @@
1
+ module Locomotive
2
+ class Account
3
+
4
+ include Locomotive::Mongoid::Document
5
+
6
+ devise *Locomotive.config.devise_modules
7
+
8
+ ## devise fields (need to be declared since 2.x) ##
9
+ field :remember_created_at, :type => Time
10
+ field :email, :type => String, :null => false
11
+ field :encrypted_password, :type => String, :null => false
12
+ field :authentication_token, :type => String
13
+ field :reset_password_token, :type => String
14
+ field :reset_password_sent_at, :type => Time
15
+ field :password_salt, :type => String
16
+ field :sign_in_count, :type => Integer
17
+ field :current_sign_in_at, :type => Time
18
+ field :last_sign_in_at, :type => Time
19
+ field :current_sign_in_ip, :type => String
20
+ field :last_sign_in_ip, :type => String
21
+
22
+ ## attributes ##
23
+ field :name
24
+ field :locale, :default => Locomotive.config.default_locale.to_s or 'en'
25
+
26
+ ## validations ##
27
+ validates_presence_of :name
28
+
29
+ ## associations ##
30
+
31
+ ## callbacks ##
32
+ before_destroy :remove_memberships!
33
+
34
+ ## methods ##
35
+
36
+ def sites
37
+ @sites ||= Site.where('memberships.account_id' => self._id)
38
+ end
39
+
40
+ # Tell if the account has admin privileges or not.
41
+ # Actually, an account is considered as an admin if
42
+ # it owns at least one admin membership in all its sites.
43
+ #
44
+ # @return [ Boolean ] True if admin
45
+ #
46
+ def admin?
47
+ Site.where(:memberships => { '$elemMatch' => { :account_id => self._id, :role => :admin } }).count > 0
48
+ end
49
+
50
+ # Create the API token which will be passed to all the requests to the Locomotive API.
51
+ # It requires the credentials of an account with admin role.
52
+ # If an error occurs (invalid account, ...etc), this method raises an exception that has
53
+ # to be caught somewhere.
54
+ #
55
+ # @param [ Site ] site The site where the authentication request is made
56
+ # @param [ String ] email The email of the account
57
+ # @param [ String ] password The password of the account
58
+ #
59
+ # @return [ String ] The API token
60
+ #
61
+ def self.create_api_token(site, email, password)
62
+ raise 'The request must contain the user email and password.' if email.blank? or password.blank?
63
+
64
+ account = self.where(:email => email.downcase).first
65
+
66
+ raise 'Invalid email or password.' if account.nil?
67
+
68
+ account.ensure_authentication_token!
69
+
70
+ if not account.valid_password?(password) # TODO: check admin roles
71
+ raise 'Invalid email or password.'
72
+ end
73
+
74
+ account.authentication_token
75
+ end
76
+
77
+ # Logout the user responding to the token passed in parameter from the API.
78
+ # An exception is raised if no account corresponds to the token.
79
+ #
80
+ # @param [ String ] token The API token created by the create_api_token method.
81
+ #
82
+ # @return [ String ] The API token
83
+ #
84
+ def self.invalidate_api_token(token)
85
+ account = self.where(:authentication_token => token).first
86
+
87
+ raise 'Invalid token.' if account.nil?
88
+
89
+ account.reset_authentication_token!
90
+
91
+ token
92
+ end
93
+
94
+ def devise_mailer
95
+ Locomotive::DeviseMailer
96
+ end
97
+
98
+ protected
99
+
100
+ def password_required?
101
+ !persisted? || !password.blank? || !password_confirmation.blank?
102
+ end
103
+
104
+ def remove_memberships!
105
+ self.sites.each do |site|
106
+ membership = site.memberships.where(:account_id => self._id).first
107
+
108
+ if site.admin_memberships.size == 1 && membership.admin?
109
+ raise ::I18n.t('errors.messages.needs_admin_account')
110
+ else
111
+ membership.destroy
112
+ end
113
+ end
114
+ end
115
+
116
+ end
117
+ end
@@ -0,0 +1,40 @@
1
+ module Locomotive
2
+ class ContentAsset
3
+
4
+ include Locomotive::Mongoid::Document
5
+
6
+ ## extensions ##
7
+ include Extensions::Asset::Types
8
+ include Extensions::Asset::Vignette
9
+
10
+ ## fields ##
11
+ field :content_type, :type => String
12
+ field :width, :type => Integer
13
+ field :height, :type => Integer
14
+ field :size, :type => Integer
15
+ field :position, :type => Integer, :default => 0
16
+
17
+ ## associations ##
18
+ belongs_to :site, :class_name => 'Locomotive::Site'
19
+
20
+ ## validations ##
21
+ validates_presence_of :source
22
+
23
+ ## behaviours ##
24
+ mount_uploader :source, ContentAssetUploader, :mount_on => :source_filename
25
+
26
+ ## methods ##
27
+
28
+ alias :name :source_filename
29
+
30
+ def extname
31
+ return nil unless self.source?
32
+ File.extname(self.source_filename).gsub(/^\./, '')
33
+ end
34
+
35
+ def to_liquid
36
+ { :url => self.source.url }.merge(self.attributes).stringify_keys
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,197 @@
1
+ module Locomotive
2
+ class ContentEntry
3
+
4
+ include Locomotive::Mongoid::Document
5
+
6
+ ## extensions ##
7
+ include ::CustomFields::Target
8
+ include Extensions::Shared::Seo
9
+
10
+ ## fields ##
11
+ field :_slug
12
+ field :_label_field_name
13
+ field :_position, :type => Integer, :default => 0
14
+ field :_visible, :type => Boolean, :default => true
15
+
16
+ ## validations ##
17
+ validates :_slug, :presence => true, :uniqueness => { :scope => :content_type_id }
18
+
19
+ ## associations ##
20
+ belongs_to :site, :class_name => 'Locomotive::Site'
21
+ belongs_to :content_type, :class_name => 'Locomotive::ContentType', :inverse_of => :entries
22
+
23
+ ## callbacks ##
24
+ before_validation :set_slug
25
+ before_save :set_site
26
+ before_save :set_visibility
27
+ before_save :set_label_field_name
28
+ before_create :add_to_list_bottom
29
+ after_create :send_notifications
30
+
31
+ ## named scopes ##
32
+ scope :visible, :where => { :_visible => true }
33
+ scope :latest_updated, :order_by => :updated_at.desc, :limit => Locomotive.config.ui[:latest_entries_nb]
34
+
35
+ ## methods ##
36
+
37
+ alias :visible? :_visible?
38
+ alias :_permalink :_slug
39
+ alias :_permalink= :_slug=
40
+
41
+ # Any content entry owns a label property which is used in the back-office UI
42
+ # to represent it. The field used as the label is defined within the parent content type.
43
+ #
44
+ # @param [ Object ] (optional) The content type to avoid to run another MongoDB and useless query.
45
+ #
46
+ # @return [ String ] The "label" of the content entry
47
+ #
48
+ def _label(type = nil)
49
+ value = if self._label_field_name
50
+ self.send(self._label_field_name.to_sym)
51
+ else
52
+ self.send((type || self.content_type).label_field_name.to_sym)
53
+ end
54
+
55
+ value.respond_to?(:to_label) ? value.to_label : value.to_s
56
+ end
57
+
58
+ alias :to_label :_label
59
+
60
+ # Tell if the content entry has been translated or not.
61
+ # It just checks if the field used for the label has been translated.
62
+ #
63
+ # @return [ Boolean ] True if translated, false otherwise
64
+ #
65
+ def translated?
66
+ if self.respond_to?(:"#{self._label_field_name}_translations")
67
+ self.send(:"#{self._label_field_name}_translations").key?(::Mongoid::Fields::I18n.locale.to_s) #rescue false
68
+ else
69
+ true
70
+ end
71
+ end
72
+
73
+ # Return the locales the content entry has been translated to.
74
+ #
75
+ # @return [ Array ] The list of locales. Nil if not localized
76
+ #
77
+ def translated_in
78
+ if self.respond_to?(:"#{self._label_field_name}_translations")
79
+ self.send(:"#{self._label_field_name}_translations").keys
80
+ else
81
+ nil
82
+ end
83
+ end
84
+
85
+ # Return the next content entry based on the order defined in the parent content type.
86
+ #
87
+ # @param [ Object ] The next content entry or nil if not found
88
+ #
89
+ def next
90
+ next_or_previous :gt
91
+ end
92
+
93
+ # Return the previous content entry based on the order defined in the parent content type.
94
+ #
95
+ # @param [ Object ] The previous content entry or nil if not found
96
+ #
97
+ def previous
98
+ next_or_previous :lt
99
+ end
100
+
101
+ # Find a content entry by its permalink
102
+ #
103
+ # @param [ String ] The permalink
104
+ #
105
+ # @return [ Object ] The content entry matching the permalink or nil if not found
106
+ #
107
+ def self.find_by_permalink(permalink)
108
+ self.where(:_slug => permalink).first
109
+ end
110
+
111
+ # Sort the content entries from an ordered array of content entry ids.
112
+ # Their new positions are persisted.
113
+ #
114
+ # @param [ Array ] The ordered array of ids
115
+ #
116
+ def self.sort_entries!(ids)
117
+ list = self.any_in(:_id => ids.map { |id| BSON::ObjectId.from_string(id.to_s) }).to_a
118
+ ids.each_with_index do |id, position|
119
+ if entry = list.detect { |e| e._id.to_s == id.to_s }
120
+ entry.update_attributes :_position => position
121
+ end
122
+ end
123
+ end
124
+
125
+ protected
126
+
127
+ # Retrieve the next or the previous entry following the order
128
+ # defined in the parent content type.
129
+ #
130
+ # @param [ Symbol ] :gt for the next element, :lt for the previous element
131
+ #
132
+ # @return [ Object ] The next or previous content entry or nil if none
133
+ #
134
+ def next_or_previous(matcher = :gt)
135
+ order_by = self.content_type.order_by_definition(matcher == :lt)
136
+ criterion = self.content_type.order_by_attribute.to_sym.send(matcher)
137
+ value = self.send(self.content_type.order_by_attribute.to_sym)
138
+
139
+ self.class.where(criterion => value).order_by([order_by]).limit(1).first
140
+ end
141
+
142
+ # Sets the slug of the instance by using the value of the highlighted field
143
+ # (if available). If a sibling content instance has the same permalink then a
144
+ # unique one will be generated
145
+ def set_slug
146
+ self._slug = self._label.dup if self._slug.blank? && self._label.present?
147
+
148
+ if self._slug.present?
149
+ self._slug.permalink!
150
+ self._slug = self.next_unique_slug if self.slug_already_taken?
151
+ end
152
+ end
153
+
154
+ # Return the next available unique slug as a string
155
+ def next_unique_slug
156
+ slug = self._slug.gsub(/-\d*$/, '')
157
+ last_slug = self.class.where(:_id.ne => self._id, :_slug => /^#{slug}-?\d*?$/i).order_by(:_slug).last._slug
158
+ next_number = last_slug.scan(/-(\d)$/).flatten.first.to_i + 1
159
+ [slug, next_number].join('-')
160
+ end
161
+
162
+ def slug_already_taken?
163
+ self.class.where(:_id.ne => self._id, :_slug => self._slug).any?
164
+ end
165
+
166
+ def set_site
167
+ self.site ||= self.content_type.site
168
+ end
169
+
170
+ def set_visibility
171
+ if self.respond_to?(:visible)
172
+ self.visible = true if self.visible.nil?
173
+ self._visible = self.visible
174
+ return
175
+ end
176
+ end
177
+
178
+ def set_label_field_name
179
+ self._label_field_name = self.content_type.label_field_name
180
+ end
181
+
182
+ def add_to_list_bottom
183
+ self._position = self.class.max(:_position).to_i + 1
184
+ end
185
+
186
+ def send_notifications
187
+ return if !self.content_type.public_submission_enabled? || self.content_type.public_submission_accounts.blank?
188
+
189
+ self.site.accounts.each do |account|
190
+ next unless self.content_type.public_submission_accounts.map(&:to_s).include?(account._id.to_s)
191
+
192
+ Locomotive::Notifications.new_content_entry(account, self).deliver
193
+ end
194
+ end
195
+
196
+ end
197
+ end
@@ -0,0 +1,224 @@
1
+ module Locomotive
2
+ class ContentType
3
+
4
+ include Locomotive::Mongoid::Document
5
+
6
+ ## extensions ##
7
+ include CustomFields::Source
8
+ include Extensions::ContentType::DefaultValues
9
+ include Extensions::ContentType::ItemTemplate
10
+ include Extensions::ContentType::Sync
11
+
12
+ ## fields ##
13
+ field :name
14
+ field :description
15
+ field :slug
16
+ field :label_field_id, :type => BSON::ObjectId
17
+ field :label_field_name
18
+ field :group_by_field_id, :type => BSON::ObjectId
19
+ field :order_by
20
+ field :order_direction, :default => 'asc'
21
+ field :public_submission_enabled, :type => Boolean, :default => false
22
+ field :public_submission_accounts, :type => Array
23
+
24
+ ## associations ##
25
+ belongs_to :site, :class_name => 'Locomotive::Site'
26
+ has_many :entries, :class_name => 'Locomotive::ContentEntry', :dependent => :destroy
27
+
28
+ ## named scopes ##
29
+ scope :ordered, :order_by => :updated_at.desc
30
+
31
+ ## indexes ##
32
+ index [[:site_id, Mongo::ASCENDING], [:slug, Mongo::ASCENDING]]
33
+
34
+ ## callbacks ##
35
+ before_validation :normalize_slug
36
+ before_validation :sanitize_public_submission_accounts
37
+ after_validation :bubble_fields_errors_up
38
+ before_update :update_label_field_name_in_entries
39
+
40
+ ## validations ##
41
+ validates_presence_of :site, :name, :slug
42
+ validates_uniqueness_of :slug, :scope => :site_id
43
+ validates_size_of :entries_custom_fields, :minimum => 1, :message => :too_few_custom_fields
44
+
45
+ ## behaviours ##
46
+ custom_fields_for :entries
47
+
48
+ ## methods ##
49
+
50
+ def order_manually?
51
+ self.order_by == '_position'
52
+ end
53
+
54
+ def order_by_definition(reverse_order = false)
55
+ direction = self.order_manually? ? 'asc' : self.order_direction || 'asc'
56
+
57
+ if reverse_order
58
+ direction = (direction == 'asc' ? 'desc' : 'asc')
59
+ end
60
+
61
+ [order_by_attribute, direction]
62
+ end
63
+
64
+ def ordered_entries(conditions = {})
65
+ _order_by_definition = (conditions || {}).delete(:order_by).try(:split) || self.order_by_definition
66
+ self.entries.order_by([_order_by_definition]).where(conditions)
67
+ end
68
+
69
+ def groupable?
70
+ !!self.group_by_field && %w(select belongs_to).include?(group_by_field.type)
71
+ end
72
+
73
+ def group_by_field
74
+ self.find_entries_custom_field(self.group_by_field_id)
75
+ end
76
+
77
+ def list_or_group_entries
78
+ if self.groupable?
79
+ if group_by_field.type == 'select'
80
+ self.entries.group_by_select_option(self.group_by_field.name, self.order_by_definition)
81
+ else
82
+ group_by_belongs_to_field(self.group_by_field)
83
+ end
84
+ else
85
+ self.ordered_entries
86
+ end
87
+ end
88
+
89
+ def class_name_to_content_type(class_name)
90
+ self.class.class_name_to_content_type(class_name, self.site)
91
+ end
92
+
93
+ def label_field_id=(value)
94
+ # update the label_field_name if the label_field_id is changed
95
+ new_label_field_name = self.entries_custom_fields.where(:_id => value).first.try(:name)
96
+ self.label_field_name = new_label_field_name
97
+ super(value)
98
+ end
99
+
100
+ def label_field_name=(value)
101
+ # mandatory if we allow the API to set the label field name without an id of the field
102
+ @new_label_field_name = value unless value.blank?
103
+ super(value)
104
+ end
105
+
106
+ # Get the class name of the entries.
107
+ #
108
+ # @return [ String ] The class name of all the entries
109
+ #
110
+ def entries_class_name
111
+ self.klass_with_custom_fields(:entries).to_s
112
+ end
113
+
114
+ # Find a custom field describing an entry based on its id
115
+ # in first or its name if not found.
116
+ #
117
+ # @param [ String ] id_or_name The id of name of the field
118
+ #
119
+ # @return [ Object ] The custom field or nit if not found
120
+ #
121
+ def find_entries_custom_field(id_or_name)
122
+ return nil if id_or_name.nil? # bypass the memoization
123
+
124
+ _field = self.entries_custom_fields.find(id_or_name) rescue nil
125
+ _field || self.entries_custom_fields.where(:name => id_or_name).first
126
+ end
127
+
128
+ # Retrieve from a class name the associated content type within the scope of a site.
129
+ # If no content type is found, the method returns nil
130
+ #
131
+ # @param [ String ] class_name The class name
132
+ # @param [ Locomotive::Site ] site The Locomotive site
133
+ #
134
+ # @return [ Locomotive::ContentType ] The content type matching the class_name
135
+ #
136
+ def self.class_name_to_content_type(class_name, site)
137
+ if class_name =~ /^Locomotive::Entry(.*)/
138
+ site.content_types.find($1)
139
+ else
140
+ nil
141
+ end
142
+ end
143
+
144
+ protected
145
+
146
+ def group_by_belongs_to_field(field)
147
+ grouped_entries = self.ordered_entries.group_by(&:"#{field.name}_id")
148
+ columns = grouped_entries.keys
149
+ target_content_type = self.class_name_to_content_type(field.class_name)
150
+ all_columns = target_content_type.ordered_entries
151
+
152
+ all_columns.map do |column|
153
+ if columns.include?(column._id)
154
+ {
155
+ :name => column._label(target_content_type),
156
+ :entries => grouped_entries.delete(column._id)
157
+ }
158
+ else
159
+ nil
160
+ end
161
+ end.compact.tap do |groups|
162
+ unless grouped_entries.empty? # "orphans" ?
163
+ groups << { :name => nil, :entries => grouped_entries.values.flatten }
164
+ end
165
+ end
166
+ end
167
+
168
+ def order_by_attribute
169
+ return self.order_by if %w(created_at updated_at _position).include?(self.order_by)
170
+ self.entries_custom_fields.find(self.order_by).name rescue 'created_at'
171
+ end
172
+
173
+ def normalize_slug
174
+ self.slug = self.name.clone if self.slug.blank? && self.name.present?
175
+ self.slug.permalink! if self.slug.present?
176
+ end
177
+
178
+ # We do not want to have a blank value in the list of accounts.
179
+ def sanitize_public_submission_accounts
180
+ if self.public_submission_accounts
181
+ self.public_submission_accounts.reject! { |id| id.blank? }
182
+ end
183
+ end
184
+
185
+ def bubble_fields_errors_up
186
+ return if self.errors[:entries_custom_fields].empty?
187
+
188
+ hash = { :base => self.errors[:entries_custom_fields] }
189
+
190
+ self.entries_custom_fields.each do |field|
191
+ next if field.valid?
192
+ key = field.persisted? ? field._id.to_s : field.position.to_i
193
+ hash[key] = field.errors.to_a
194
+ end
195
+
196
+ self.errors.set(:entries_custom_fields, hash)
197
+ end
198
+
199
+ def update_label_field_name_in_entries
200
+ self.klass_with_custom_fields(:entries).update_all :_label_field_name => self.label_field_name
201
+ end
202
+
203
+ # Makes sure the class_name filled in a belongs_to or has_many field
204
+ # does not belong to another site. Adds an error if it presents a
205
+ # security problem.
206
+ #
207
+ # @param [ CustomFields::Field ] field The field to check
208
+ #
209
+ def ensure_class_name_security(field)
210
+ if field.class_name =~ /^Locomotive::Entry([a-z0-9]+)$/
211
+ content_type = Locomotive::ContentType.find($1)
212
+
213
+ if content_type.site_id != self.site_id
214
+ field.errors.add :class_name, :security
215
+ end
216
+ else
217
+ # for now, does not allow external classes
218
+ field.errors.add :class_name, :security
219
+ end
220
+ end
221
+
222
+ end
223
+ end
224
+