locomotivecms 3.0.0.pre.beta.1 → 3.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (175) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +4 -3
  3. data/app/api/locomotive/api.rb +1 -0
  4. data/app/api/locomotive/api/entities/page_entity.rb +1 -1
  5. data/app/api/locomotive/api/entities/site_entity.rb +9 -1
  6. data/app/api/locomotive/api/exception_rescuers.rb +3 -5
  7. data/app/api/locomotive/api/forms/page_form.rb +1 -1
  8. data/app/api/locomotive/api/forms/site_form.rb +1 -2
  9. data/app/api/locomotive/api/helpers/authentication_helper.rb +6 -1
  10. data/app/api/locomotive/api/helpers/locales_helper.rb +15 -0
  11. data/app/api/locomotive/api/helpers/params_helper.rb +13 -0
  12. data/app/api/locomotive/api/middlewares/locale_middleware.rb +6 -1
  13. data/app/api/locomotive/api/resources/content_entry_resource.rb +2 -0
  14. data/app/api/locomotive/api/resources/content_type_resource.rb +2 -2
  15. data/app/api/locomotive/api/resources/current_site_resource.rb +2 -1
  16. data/app/api/locomotive/api/resources/membership_resource.rb +0 -4
  17. data/app/api/locomotive/api/resources/page_resource.rb +6 -1
  18. data/app/api/locomotive/api/resources/site_resource.rb +4 -2
  19. data/app/assets/javascripts/locomotive.js +1 -0
  20. data/app/assets/javascripts/locomotive/utils/nprogress.js.coffee +3 -1
  21. data/app/assets/javascripts/locomotive/views/editable_elements/index_view.js.coffee +10 -3
  22. data/app/assets/javascripts/locomotive/views/inputs/markdown_view.js.coffee +82 -0
  23. data/app/assets/javascripts/locomotive/views/inputs/rte/file_view.js.coffee +1 -1
  24. data/app/assets/javascripts/locomotive/views/inputs/rte/link_view.js.coffee +1 -1
  25. data/app/assets/javascripts/locomotive/views/inputs/rte_view.js.coffee.erb +1 -1
  26. data/app/assets/javascripts/locomotive/views/inputs/text_view.js.coffee +4 -1
  27. data/app/assets/javascripts/locomotive/views/pages/list_view.js.coffee +3 -0
  28. data/app/assets/javascripts/locomotive/views/shared/form_view.js.coffee +22 -1
  29. data/app/assets/javascripts/locomotive/views/shared/header_view.js.coffee +2 -2
  30. data/app/assets/stylesheets/locomotive/application.scss +2 -0
  31. data/app/assets/stylesheets/locomotive/base/_form.scss +2 -0
  32. data/app/assets/stylesheets/locomotive/base/form/_api_key.scss +0 -1
  33. data/app/assets/stylesheets/locomotive/base/form/_array_input.scss +2 -0
  34. data/app/assets/stylesheets/locomotive/base/form/_base.scss +13 -2
  35. data/app/assets/stylesheets/locomotive/base/form/_color_input.scss +12 -0
  36. data/app/assets/stylesheets/locomotive/base/form/_markdown.scss +292 -0
  37. data/app/assets/stylesheets/locomotive/base/form/_popover.scss +22 -0
  38. data/app/assets/stylesheets/locomotive/base/form/_rte.scss +2 -1
  39. data/app/assets/stylesheets/locomotive/components/_activity_feed.scss +1 -0
  40. data/app/assets/stylesheets/locomotive/components/_dashboard.scss +29 -0
  41. data/app/assets/stylesheets/locomotive/components/_live_editing.scss +13 -1
  42. data/app/assets/stylesheets/locomotive/components/_main.scss +1 -1
  43. data/app/assets/stylesheets/locomotive/components/_transitions.scss +24 -3
  44. data/app/assets/stylesheets/locomotive/components/sidebar/_base.scss +1 -0
  45. data/app/assets/stylesheets/locomotive/globals/_bootstrap.scss +2 -2
  46. data/app/assets/stylesheets/locomotive/globals/_variables.scss +4 -3
  47. data/app/assets/stylesheets/locomotive/layouts/_live_editing.scss +4 -0
  48. data/app/controllers/locomotive/concerns/locale_helpers_controller.rb +1 -0
  49. data/app/controllers/locomotive/content_entries_controller.rb +10 -2
  50. data/app/controllers/locomotive/pages_controller.rb +2 -1
  51. data/app/controllers/locomotive/passwords_controller.rb +17 -1
  52. data/app/helpers/locomotive/base_helper.rb +19 -0
  53. data/app/helpers/locomotive/content_types_helper.rb +2 -1
  54. data/app/helpers/locomotive/custom_fields_helper.rb +14 -1
  55. data/app/helpers/locomotive/dashboard_helper.rb +12 -0
  56. data/app/helpers/locomotive/editable_elements_helper.rb +9 -4
  57. data/app/helpers/locomotive/pages_helper.rb +1 -14
  58. data/app/helpers/locomotive/shared/pages_helper.rb +17 -0
  59. data/app/helpers/locomotive/translations_helper.rb +0 -14
  60. data/app/inputs/locomotive/color_input.rb +18 -0
  61. data/app/inputs/locomotive/markdown_input.rb +19 -0
  62. data/app/models/locomotive/account.rb +2 -1
  63. data/app/models/locomotive/concerns/content_entry/file_size.rb +27 -0
  64. data/app/models/locomotive/concerns/content_type/group_by.rb +3 -1
  65. data/app/models/locomotive/concerns/page/layout.rb +63 -19
  66. data/app/models/locomotive/concerns/shared/site_scope.rb +37 -0
  67. data/app/models/locomotive/concerns/site/cache.rb +32 -0
  68. data/app/models/locomotive/concerns/theme_asset/plain_text.rb +85 -0
  69. data/app/models/locomotive/content_entry.rb +7 -7
  70. data/app/models/locomotive/content_type.rb +12 -6
  71. data/app/models/locomotive/page.rb +12 -14
  72. data/app/models/locomotive/site.rb +9 -3
  73. data/app/models/locomotive/snippet.rb +6 -4
  74. data/app/models/locomotive/theme_asset.rb +8 -73
  75. data/app/models/locomotive/translation.rb +6 -5
  76. data/app/policies/locomotive/site_policy.rb +2 -2
  77. data/app/services/locomotive/content_entry_service.rb +7 -6
  78. data/app/services/locomotive/site_service.rb +1 -0
  79. data/app/views/locomotive/content_entries/_entry.html.slim +1 -0
  80. data/app/views/locomotive/content_entries/edit.html.slim +1 -1
  81. data/app/views/locomotive/content_entries/new.html.slim +1 -1
  82. data/app/views/locomotive/current_site/_membership.html.slim +1 -0
  83. data/app/views/locomotive/current_site/edit.html.slim +1 -1
  84. data/app/views/locomotive/current_site/form/_access_points.html.slim +1 -1
  85. data/app/views/locomotive/current_site/form/_advanced.html.slim +2 -0
  86. data/app/views/locomotive/dashboard/_activity.html.slim +26 -0
  87. data/app/views/locomotive/dashboard/_url.html.slim +9 -0
  88. data/app/views/locomotive/dashboard/show.html.slim +3 -21
  89. data/app/views/locomotive/devise_mailer/reset_password_instructions.html.slim +1 -1
  90. data/app/views/locomotive/editable_elements/_edit.html.slim +8 -1
  91. data/app/views/locomotive/editable_elements/_form.html.slim +1 -1
  92. data/app/views/locomotive/editable_elements/index_without_preview.html.slim +24 -17
  93. data/app/views/locomotive/layouts/application.html.slim +6 -4
  94. data/app/views/locomotive/layouts/live_editing.html.slim +9 -0
  95. data/app/views/locomotive/layouts/not_logged_in.html.slim +1 -1
  96. data/app/views/locomotive/layouts/without_site.html.slim +2 -0
  97. data/app/views/locomotive/memberships/edit.html.slim +1 -1
  98. data/app/views/locomotive/memberships/new.html.slim +1 -1
  99. data/app/views/locomotive/my_account/edit.html.slim +7 -5
  100. data/app/views/locomotive/pages/_header.html.slim +7 -0
  101. data/app/views/locomotive/pages/edit.html.slim +2 -4
  102. data/app/views/locomotive/pages/form/_main.html.slim +4 -1
  103. data/app/views/locomotive/pages/form/_tabs.html.slim +4 -3
  104. data/app/views/locomotive/public_submission_accounts/_account.html.slim +1 -1
  105. data/app/views/locomotive/public_submission_accounts/edit.html.slim +1 -1
  106. data/app/views/locomotive/shared/_header.html.slim +25 -22
  107. data/app/views/locomotive/shared/_locale_picker_link.html.slim +3 -0
  108. data/app/views/locomotive/shared/_main_app_header.html.slim +1 -1
  109. data/app/views/locomotive/shared/_sidebar.html.slim +15 -11
  110. data/app/views/locomotive/shared/rte/_markdown_toolbar.html.slim +42 -0
  111. data/config/locales/admin_ui.en.yml +9 -4
  112. data/config/locales/default.en.yml +4 -0
  113. data/config/locales/devise.en.yml +1 -0
  114. data/config/locales/simple_form.en.yml +6 -2
  115. data/lib/locomotive/action_controller/responder.rb +5 -0
  116. data/lib/locomotive/engine.rb +5 -0
  117. data/lib/locomotive/middlewares/site.rb +39 -21
  118. data/lib/locomotive/simple_form.rb +3 -31
  119. data/lib/locomotive/steam/middlewares/cache.rb +62 -0
  120. data/lib/locomotive/steam/middlewares/page_editing.rb +9 -3
  121. data/lib/locomotive/steam/services/api_entry_submission_service.rb +6 -3
  122. data/lib/locomotive/steam/services/liquid_parser_with_cache_service.rb +74 -0
  123. data/lib/locomotive/steam_adaptor.rb +7 -1
  124. data/lib/locomotive/version.rb +1 -1
  125. data/lib/tasks/development.rake +4 -0
  126. data/lib/tasks/locomotive.rake +14 -0
  127. data/spec/lib/locomotive/steam/services/api_entry_submission_service_spec.rb +10 -1
  128. data/spec/lib/locomotive/steam/services/liquid_parser_with_cache_service_spec.rb +53 -0
  129. data/spec/models/locomotive/concerns/content_entry/file_size_spec.rb +40 -0
  130. data/spec/models/locomotive/concerns/page/layout_spec.rb +122 -17
  131. data/spec/models/locomotive/concerns/site/cache_spec.rb +60 -0
  132. data/spec/models/locomotive/content_entry_spec.rb +7 -0
  133. data/spec/models/locomotive/content_type_spec.rb +18 -11
  134. data/spec/models/locomotive/page_spec.rb +32 -8
  135. data/spec/models/locomotive/snippet_spec.rb +13 -4
  136. data/spec/models/locomotive/theme_asset_spec.rb +10 -3
  137. data/spec/models/locomotive/translation_spec.rb +28 -0
  138. data/spec/requests/locomotive/steam/cache_spec.rb +83 -0
  139. data/spec/requests/site_spec.rb +24 -0
  140. data/spec/support/capybara.rb +5 -13
  141. data/spec/support/factories.rb +9 -0
  142. data/spec/support/features/session_helpers.rb +19 -3
  143. data/spec/support/features/site_helpers.rb +27 -0
  144. data/spec/support/shared_examples/site_scope_examples.rb +27 -0
  145. data/vendor/assets/images/locomotive/bootstrap-colorpicker/alpha-horizontal.png +0 -0
  146. data/vendor/assets/images/locomotive/bootstrap-colorpicker/alpha.png +0 -0
  147. data/vendor/assets/images/locomotive/bootstrap-colorpicker/hue-horizontal.png +0 -0
  148. data/vendor/assets/images/locomotive/bootstrap-colorpicker/hue.png +0 -0
  149. data/vendor/assets/images/locomotive/bootstrap-colorpicker/saturation.png +0 -0
  150. data/vendor/assets/javascripts/locomotive/bootstrap-colorpicker.js +1 -0
  151. data/vendor/assets/javascripts/locomotive/datepicker_i18n.js.erb +6 -6
  152. data/vendor/assets/javascripts/locomotive/kramed.min.js +11 -0
  153. data/vendor/assets/stylesheets/locomotive/bootstrap-colorpicker.scss +9 -0
  154. metadata +59 -44
  155. data/app/controllers/locomotive/api/accounts_controller.rb +0 -60
  156. data/app/controllers/locomotive/api/base_controller.rb +0 -35
  157. data/app/controllers/locomotive/api/content_assets_controller.rb +0 -51
  158. data/app/controllers/locomotive/api/content_entries_controller.rb +0 -71
  159. data/app/controllers/locomotive/api/content_types_controller.rb +0 -52
  160. data/app/controllers/locomotive/api/current_site_controller.rb +0 -34
  161. data/app/controllers/locomotive/api/memberships_controller.rb +0 -52
  162. data/app/controllers/locomotive/api/my_account_controller.rb +0 -46
  163. data/app/controllers/locomotive/api/pages_controller.rb +0 -53
  164. data/app/controllers/locomotive/api/sites_controller.rb +0 -58
  165. data/app/controllers/locomotive/api/snippets_controller.rb +0 -52
  166. data/app/controllers/locomotive/api/theme_assets_controller.rb +0 -51
  167. data/app/controllers/locomotive/api/tokens_controller.rb +0 -36
  168. data/app/controllers/locomotive/api/translations_controller.rb +0 -51
  169. data/app/controllers/locomotive/api/version_controller.rb +0 -11
  170. data/spec/models/locomotive/editable_control_spec.rb +0 -79
  171. data/spec/models/locomotive/editable_file_spec.rb +0 -94
  172. data/spec/models/locomotive/editable_text_spec.rb +0 -219
  173. data/vendor/assets/images/select2-spinner.gif +0 -0
  174. data/vendor/assets/images/select2.png +0 -0
  175. data/vendor/assets/images/select2x2.png +0 -0
@@ -1 +1 @@
1
- - # this partial can be overridden in the main app in order to include a search bar for instance
1
+ - # this partial can be overridden in the main app in order to include a warning message for instance
@@ -1,22 +1,26 @@
1
1
  = render 'locomotive/shared/sidebar/my_account'
2
2
 
3
- = render 'locomotive/shared/sidebar/link', icon: 'fa-dashboard', label: t('.dashboard'), url: dashboard_path(current_site)
3
+ - cache(cache_key_for_sidebar) do
4
4
 
5
- = render_pages
5
+ = render 'locomotive/shared/sidebar/link', icon: 'fa-dashboard', label: t('.dashboard'), url: dashboard_path(current_site)
6
6
 
7
- = render 'locomotive/shared/sidebar/content_types'
7
+ - cache(cache_key_for_sidebar_pages) do
8
+ = render_pages
8
9
 
9
- = render 'locomotive/shared/sidebar/link', icon: 'fa-picture-o', label: t('.assets'), url: content_assets_path(current_site)
10
+ - cache(cache_key_for_sidebar_content_types) do
11
+ = render 'locomotive/shared/sidebar/content_types'
10
12
 
11
- - if current_site.localized?
12
- = render 'locomotive/shared/sidebar/link', icon: 'fa-globe', label: t('.translations'), url: translations_path(current_site)
13
+ = render 'locomotive/shared/sidebar/link', icon: 'fa-picture-o', label: t('.assets'), url: content_assets_path(current_site)
13
14
 
14
- = render 'locomotive/shared/sidebar/link', icon: 'fa-gear', label: t('.settings'), url: edit_current_site_path(current_site)
15
+ - if current_site.localized?
16
+ = render 'locomotive/shared/sidebar/link', icon: 'fa-globe', label: t('.translations'), url: translations_path(current_site)
15
17
 
16
- - if policy(current_site).show_developers_documentation?
17
- = render 'locomotive/shared/sidebar/link', icon: 'fa-book', label: t('.developers'), url: developers_documentation_path(current_site)
18
+ = render 'locomotive/shared/sidebar/link', icon: 'fa-gear', label: t('.settings'), url: edit_current_site_path(current_site)
18
19
 
19
- = render 'locomotive/shared/sidebar/link', icon: 'fa-suitcase', label: t(:sites, scope: 'locomotive.shared.header'), url: sites_path, section_class: 'visible-xs-block'
20
+ - if policy(current_site).show_developers_documentation?
21
+ = render 'locomotive/shared/sidebar/link', icon: 'fa-book', label: t('.developers'), url: developers_documentation_path(current_site)
20
22
 
21
- = render 'locomotive/shared/sidebar/link', icon: 'fa-sign-out', label: t(:logout, scope: 'locomotive.shared.header'), url: destroy_locomotive_account_session_path, data: { confirm: t('locomotive.messages.confirm') }, section_class: 'visible-xs-block'
23
+ = render 'locomotive/shared/sidebar/link', icon: 'fa-suitcase', label: t(:sites, scope: 'locomotive.shared.header'), url: sites_path, section_class: 'visible-xs-block'
24
+
25
+ = render 'locomotive/shared/sidebar/link', icon: 'fa-sign-out', label: t(:logout, scope: 'locomotive.shared.header'), url: destroy_locomotive_account_session_path, data: { confirm: t('locomotive.messages.confirm') }, section_class: 'visible-xs-block'
22
26
 
@@ -0,0 +1,42 @@
1
+ .wysihtml5-toolbar id="markdown-toolbar-#{wysihtml5_prefix}"
2
+
3
+ span.wysihtml5-toolbar-group
4
+ a data-markdown-command='bold'
5
+ i.fa.fa-bold
6
+ a data-markdown-command='italic'
7
+ i.fa.fa-italic
8
+
9
+ span.wysihtml5-toolbar-group
10
+ / a data-markdown-command='insertUnorderedList'
11
+ / i.fa.fa-list-ul
12
+ / a data-markdown-command='insertOrderedList'
13
+ / i.fa.fa-list-ol
14
+ / a.style
15
+ / i.fa.fa-paragraph
16
+
17
+ / .style-dialog-content style='display: none'
18
+ / a data-markdown-command='formatBlock' data-markdown-command-value='h1' H1
19
+ / br
20
+ / a data-markdown-command='formatBlock' data-markdown-command-value='h2' H2
21
+ / br
22
+ / a data-markdown-command='formatBlock' data-markdown-command-value='h3' H3
23
+ / br
24
+ / a data-markdown-command='formatBlock' data-markdown-command-value='h3' H4
25
+ / br
26
+ / a data-markdown-command='formatBlock' data-markdown-command-value='h3' H5
27
+ / br
28
+ / a data-markdown-command='formatBlock' data-markdown-command-value='h3' H6
29
+ / br
30
+ / a data-markdown-command='formatBlock' data-markdown-command-value='blockquote'
31
+ / i.fa.fa-quote-right
32
+ / br
33
+
34
+ / a data-markdown-command='createLink'
35
+ / i.fa.fa-chain
36
+ / = link_popover
37
+ / a data-markdown-command='removeLink'
38
+ / i.fa.fa-chain-broken
39
+
40
+ a data-url=content_assets_path data-markdown-command='insertFile'
41
+ i.fa.fa-file-o
42
+ = image_popover
@@ -73,7 +73,7 @@ en:
73
73
  title: Site not found
74
74
  next: "Next →"
75
75
  message:
76
- create_account: "Please create first an account and then create a site."
76
+ create_account: "Please create an account first and then create a site."
77
77
  add_domain: "Add the <strong>%{host}</strong> domain to the list of domains of one of your sites."
78
78
  sign_in: "Please sign in first. Then, add the <strong>%{host}</strong> domain to the list of domains of one of your sites."
79
79
 
@@ -164,7 +164,13 @@ en:
164
164
 
165
165
  dashboard:
166
166
  show:
167
- title: 'Activity'
167
+ title: 'Dashboard'
168
+ url:
169
+ title: "URL of your site:"
170
+ visit: 'Visit'
171
+ change_domain: 'Use your own domain name'
172
+ activity:
173
+ title: Activity
168
174
  unknown_account: Someone
169
175
  load_more: Loading more
170
176
  loading_activity_feed: Loading...
@@ -192,8 +198,6 @@ en:
192
198
 
193
199
  pages:
194
200
  index:
195
- title: Pages
196
- help: "Pages are organized as a tree. You can order pages as well as folders"
197
201
  no_items: "There are no pages for now. Just click <a href=\"%{url}\">here</a> to create the first one."
198
202
  new: new page
199
203
  list_content_entries: "List %{name}"
@@ -219,6 +223,7 @@ en:
219
223
  title: "%{title} &mdash; <small>%{fullpath}</small>"
220
224
  edit:
221
225
  settings_link: 'Settings'
226
+ no_editable_elements: 'No editable elements found'
222
227
  form:
223
228
  model:
224
229
  buttons:
@@ -15,6 +15,10 @@ en:
15
15
  messages:
16
16
  blank_in_locale: "can't be blank"
17
17
  models:
18
+ locomotive/page:
19
+ attributes:
20
+ layout_id:
21
+ index_can_not_extend_parent: "The index page can't have its parent page as a layout"
18
22
  locomotive/membership:
19
23
  attributes:
20
24
  account:
@@ -25,6 +25,7 @@ en:
25
25
  locomotive_account:
26
26
  send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.'
27
27
  updated: 'Your password was changed successfully. You are now signed in.'
28
+ invalid: 'You need to ask again for a new password.'
28
29
  confirmations:
29
30
  locomotive_account:
30
31
  send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.'
@@ -1,5 +1,7 @@
1
1
  en:
2
2
  simple_form:
3
+ blank_required_fields: "You haven't filled all the required inputs."
4
+
3
5
  titles:
4
6
  locomotive:
5
7
  account:
@@ -70,6 +72,7 @@ en:
70
72
  site:
71
73
  locales: Languages
72
74
  timezone_name: Timezone
75
+ cache_enabled: Cache
73
76
  new:
74
77
  locales: First language
75
78
  membership:
@@ -96,8 +99,8 @@ en:
96
99
  page:
97
100
  handle: "Unique identifier to retrieve this page within an external controller instance"
98
101
  published: "Only authenticated accounts can view unpublished pages."
99
- cache_strategy: "Cache the page for better performance. The 'Simple' choice is a good compromise."
100
102
  templatized: "Use the page as a template for a model you defined."
103
+ cache_enabled: "When enabled, your page will be cached as long as the content doesn't change."
101
104
  listed: "Control whether to show the page from generated menus."
102
105
  target_klass_name: "The type of content this page will be a template for."
103
106
  seo_title: "Define a page title which should be used as the value for the title tag in the head section. Leave it empty if you want to use the default value from the site settings."
@@ -113,8 +116,9 @@ en:
113
116
  meta_keywords: "Meta keywords used within the head tag of the page. They are separated by a comma. Required for SEO."
114
117
  meta_description: "Meta description used within the head tag of the page. Required for SEO."
115
118
  robots_txt: "Content of the <span class='code'>/robots.txt</span> file. Check the following <a href='http://www.w3.org/TR/html4/appendix/notes.html#h-B.4.1.1'>url</a> for more information."
116
- domains: "Simply add your domains just below. <b>Do not forget to upgrade your DNS.</b>"
119
+ domains: "Add your domains just below. Then, register a CNAME DNS record pointing to <b>%{domain}</b>."
117
120
  memberships: "You can invite other accounts to edit/manage the site."
121
+ cache_enabled: "When enabled, your pages will be cached as long as the content doesn't change. Disabling cache per page is allowed."
118
122
  new:
119
123
  locales: "You can add other languages once your site will be created."
120
124
  theme_asset:
@@ -65,6 +65,11 @@ module Locomotive
65
65
  protected
66
66
 
67
67
  def with_flash_message(type = :notice, in_header = true)
68
+ unless set_flash_message?
69
+ yield if block_given?
70
+ return
71
+ end
72
+
68
73
  if in_header
69
74
  set_flash_message!
70
75
  message = URI::escape(controller.flash[type].to_str) if controller.flash[type]
@@ -31,6 +31,11 @@ module Locomotive
31
31
 
32
32
  initializer 'locomotive.precompile.hook', group: :all do |app|
33
33
  app.config.assets.precompile += %w(
34
+ locomotive/bootstrap-colorpicker/saturation.png
35
+ locomotive/bootstrap-colorpicker/alpha-horizontal.png
36
+ locomotive/bootstrap-colorpicker/alpha.png
37
+ locomotive/bootstrap-colorpicker/hue-horizontal.png
38
+ locomotive/bootstrap-colorpicker/hue.png
34
39
  locomotive/wysihtml5_reset.css
35
40
  locomotive/wysihtml5_editor.css
36
41
  locomotive.js
@@ -7,19 +7,30 @@ module Locomotive
7
7
  end
8
8
 
9
9
  def call(env)
10
- env['locomotive.site'] = env['steam.site'] = fetch_site(env)
11
- begin
10
+ request = Rack::Request.new(env)
11
+
12
+ # do not process "/assets"
13
+ # only in dev, since the assets are precompiled in production
14
+ if request_for_the_back_office_assets?(request)
12
15
  @app.call(env)
13
- rescue ::Locomotive::Steam::NoSiteException => exception
14
- # no_site!
15
- Locomotive::ErrorsController.action(:no_site).call(env)
16
+ else
17
+ env['locomotive.site'] = site = fetch_site(request)
18
+
19
+ # deal with the Steam entity instead of a Mongoid document
20
+ env['steam.site'] = site.try(:to_steam)
21
+
22
+ begin
23
+ @app.call(env)
24
+ rescue ::Locomotive::Steam::NoSiteException => exception
25
+ # no_site!
26
+ Locomotive::ErrorsController.action(:no_site).call(env)
27
+ end
16
28
  end
17
29
  end
18
30
 
19
31
  private
20
32
 
21
- def fetch_site(env)
22
- request = Rack::Request.new(env)
33
+ def fetch_site(request)
23
34
  handle = site_handle(request)
24
35
 
25
36
  return nil if handle == 'api'
@@ -27,40 +38,35 @@ module Locomotive
27
38
  Locomotive.log "[fetch site] host = #{request.host} / site_handle = #{handle.inspect}"
28
39
 
29
40
  if handle
30
- fetch_from_handle(handle, env, request)
41
+ fetch_from_handle(handle, request)
31
42
  elsif !request_for_the_back_office_and_default_host?(request)
32
- fetch_from_host(env, request)
43
+ fetch_from_host(request)
33
44
  else
34
45
  nil
35
46
  end
36
47
  end
37
48
 
38
- # def no_site!(env)
39
- # Locomotive::ErrorsController.action(:no_site).call(env)
40
- # # [200, { 'Content-Type' => 'text/html' }, ['Hello world']]
41
- # end
42
-
43
49
  # The site is not rendered from a domain but from the back-office
44
50
  # we need to get:
45
51
  # - the path of "mouting point" (basically: locomotive/:handle/preview)
46
52
  # - the real path of the page
47
53
  #
48
54
  # FIXME: move that in a different middleware
49
- def fetch_from_handle(handle, env, request)
55
+ def fetch_from_handle(handle, request)
50
56
  mounted_on = "#{Locomotive.mounted_on}/#{handle}/preview"
51
57
 
52
- env['locomotive.mounted_on'] = env['steam.mounted_on'] = mounted_on
53
- env['locomotive.path'] = request.path_info.gsub(mounted_on, '')
58
+ request.env['locomotive.mounted_on'] = request.env['steam.mounted_on'] = mounted_on
59
+ request.env['locomotive.path'] = request.path_info.gsub(mounted_on, '')
54
60
 
55
- env['steam.live_editing'] = true
61
+ request.env['steam.live_editing'] = true
56
62
 
57
63
  Locomotive::Site.where(handle: handle).first
58
64
  end
59
65
 
60
66
  # The request is for one of the domains registered in Locomotive.
61
67
  # Find the related site.
62
- def fetch_from_host(env, request)
63
- env['locomotive.path'] = request.path_info
68
+ def fetch_from_host(request)
69
+ request.env['locomotive.path'] = request.path_info
64
70
  Locomotive::Site.match_domain(request.host).first
65
71
  end
66
72
 
@@ -78,10 +84,22 @@ module Locomotive
78
84
  @regexp ||= /#{Locomotive.mounted_on}\/([^\/]+)/o
79
85
  end
80
86
 
87
+ def request_for_the_back_office_assets?(request)
88
+ default_host?(request) && request.path_info.starts_with?('/assets/')
89
+ end
90
+
81
91
  # Is it a request for the back-office AND the domain used to also
82
92
  # render the site of the Rails application?
83
93
  def request_for_the_back_office_and_default_host?(request)
84
- default_host && request.host == default_host && request.path_info =~ /#{Locomotive.mounted_on}\//
94
+ default_host?(request) && request.path_info =~ /#{Locomotive.mounted_on}\//
95
+ end
96
+
97
+ def default_host?(request)
98
+ (default_host && request.host == default_host) || localhost?(request)
99
+ end
100
+
101
+ def localhost?(request)
102
+ request.host == '0.0.0.0' || request.host == 'localhost'
85
103
  end
86
104
 
87
105
  def default_host
@@ -1,5 +1,3 @@
1
- # require 'pry-byebug'
2
-
3
1
  module Locomotive
4
2
  module SimpleForm
5
3
  module BootstrapHelpers
@@ -110,14 +108,14 @@ module Locomotive
110
108
  template.link_to(label, url)
111
109
  end
112
110
 
113
- def action(misc_class = '')
111
+ def action(options = {})
114
112
  action = object.persisted? ? :update : :create
115
- label = translate_button(action)
113
+ label = options[:label] || translate_button(action)
116
114
  loading_text = translate_button(:loading_text)
117
115
 
118
116
  template.content_tag :button, label,
119
117
  type: 'submit',
120
- class: "btn btn-success btn-sm #{misc_class}",
118
+ class: "btn btn-success btn-sm #{options[:class]}",
121
119
  data: { loading_text: loading_text }
122
120
  end
123
121
 
@@ -125,28 +123,6 @@ module Locomotive
125
123
  translate_button(action)
126
124
  end
127
125
 
128
- # # Translate text for the submits and titles namespace.
129
- # # it differs from the simple_form translate_from_namespace method
130
- # # in that this does not care about the attribute.
131
- # #
132
- # def translate_text(key, namespace, default = '')
133
- # model_names = lookup_model_names.dup
134
- # lookups = []
135
-
136
- # while !model_names.empty?
137
- # joined_model_names = model_names.join(".")
138
- # model_names.shift
139
-
140
- # lookups << :"#{joined_model_names}.#{key}"
141
- # end
142
- # lookups << :"defaults.locomotive.#{key}"
143
- # lookups << default.to_s
144
-
145
- # puts "#{i18n_scope}.#{namespace}.#{lookups.first} - #{lookups.inspect}"
146
-
147
- # I18n.t(lookups.shift, scope: :"#{i18n_scope}.#{namespace}", default: lookups).presence
148
- # end
149
-
150
126
  def translate_button(key)
151
127
  template.t("simple_form.buttons.defaults.locomotive.#{key}")
152
128
  end
@@ -171,9 +147,5 @@ module Locomotive
171
147
  end
172
148
  end
173
149
 
174
- # def i18n_scope
175
- # ::SimpleForm.i18n_scope
176
- # end
177
-
178
150
  end
179
151
  end
@@ -0,0 +1,62 @@
1
+ module Locomotive
2
+ module Steam
3
+ module Middlewares
4
+
5
+ class Cache
6
+
7
+ attr_reader :app
8
+
9
+ CACHEABLE_REQUEST_METHODS = %w(GET HEAD).freeze
10
+
11
+ def initialize(app)
12
+ @app = app
13
+ end
14
+
15
+ def call(env)
16
+ if cacheable?(env)
17
+ fetch_cached_response(env)
18
+ else
19
+ app.call(env)
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def fetch_cached_response(env)
26
+ key = cache_key(env)
27
+
28
+ if marshaled = Rails.cache.read(key)
29
+ Marshal.load(marshaled)
30
+ else
31
+ app.call(env).tap do |response|
32
+ Rails.cache.write(key, marshal(response))
33
+ end
34
+ end
35
+ end
36
+
37
+ def marshal(response)
38
+ code, headers, body = response
39
+
40
+ _headers = headers.dup.reject! { |key, val| key =~ /[^0-9A-Z_]/ || !val.respond_to?(:to_str) }
41
+
42
+ Marshal.dump([code, _headers, body])
43
+ end
44
+
45
+ def cacheable?(env)
46
+ CACHEABLE_REQUEST_METHODS.include?(env['REQUEST_METHOD']) &&
47
+ !env['steam.live_editing'] &&
48
+ env['steam.site'].try(:cache_enabled) &&
49
+ env['steam.page'].try(:cache_enabled)
50
+ end
51
+
52
+ def cache_key(env)
53
+ site, path, query = env['steam.site'], env['PATH_INFO'], env['QUERY_STRING']
54
+ key = "#{Locomotive::VERSION}/site/#{site._id}/#{site.last_modified_at.to_i}/page/#{path}/#{query}"
55
+ Digest::MD5.hexdigest(key)
56
+ end
57
+
58
+ end
59
+
60
+ end
61
+ end
62
+ end
@@ -12,9 +12,9 @@ module Locomotive
12
12
 
13
13
  def call(env)
14
14
  status, headers, response = @app.call(env)
15
- site, page, locale = env['steam.site'], env['steam.page'], env['steam.locale'].to_s
15
+ site, page, locale, live_editing = env['steam.site'], env['steam.page'], env['steam.locale'].to_s, env['steam.live_editing']
16
16
 
17
- if page && !page.redirect && page.response_type == 'text/html' && response.first
17
+ if editable?(page, response, live_editing)
18
18
  html = %(
19
19
  <meta name="locomotive-locale" content="#{locale}" />
20
20
  <meta name="locomotive-editable-elements-path" content="#{editable_elements_path(site, page, locale, env)}" />
@@ -26,6 +26,12 @@ module Locomotive
26
26
  [status, headers, response]
27
27
  end
28
28
 
29
+ protected
30
+
31
+ def editable?(page, response, live_editing)
32
+ live_editing && page && !page.redirect && page.response_type == 'text/html' && response.first
33
+ end
34
+
29
35
  def editable_elements_path(site, page, locale, env)
30
36
  options = {}
31
37
 
@@ -38,7 +44,7 @@ module Locomotive
38
44
 
39
45
  options[:content_locale] = locale if site.locales.size > 1
40
46
 
41
- super(site, page._id, options)
47
+ super(site.handle, page._id, options)
42
48
  end
43
49
 
44
50
  end