tribeca_cms 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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
+