locomotivecms 4.0.0.rc0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +1 -1
  4. data/Rakefile +0 -6
  5. data/app/api/locomotive/api/entities/site_entity.rb +1 -1
  6. data/app/api/locomotive/api/forms/content_type_form.rb +1 -0
  7. data/app/api/locomotive/api/forms/page_form.rb +2 -1
  8. data/app/api/locomotive/api/forms/site_form.rb +7 -1
  9. data/app/api/locomotive/api/helpers/persistence_helper.rb +3 -0
  10. data/app/api/locomotive/api/resources/account_resource.rb +15 -3
  11. data/app/api/locomotive/api/resources/content_type_resource.rb +3 -0
  12. data/app/api/locomotive/api/resources/membership_resource.rb +1 -1
  13. data/app/api/locomotive/api/resources/site_resource.rb +6 -0
  14. data/app/assets/javascripts/locomotive/editor.js +1311 -703
  15. data/app/assets/javascripts/locomotive/views/content_entries/edit_view.js.coffee +5 -0
  16. data/app/assets/javascripts/locomotive/views/content_entries/index_view.js.coffee +1 -0
  17. data/app/assets/javascripts/locomotive/views/content_entries/new_view.js.coffee +4 -0
  18. data/app/assets/javascripts/locomotive/views/current_site/edit_view.js.coffee +6 -0
  19. data/app/assets/javascripts/locomotive/views/page_content/edit_view.js.coffee +1 -0
  20. data/app/assets/javascripts/locomotive/views/pages/_form_view.js.coffee +6 -0
  21. data/app/assets/javascripts/locomotive/views/pages/edit_view.js.coffee +4 -0
  22. data/app/assets/javascripts/locomotive/views/pages/list_view.js.coffee +5 -0
  23. data/app/assets/javascripts/locomotive/views/pages/new_view.js.coffee +4 -0
  24. data/app/assets/stylesheets/locomotive/editor.css +390 -127
  25. data/app/assets/stylesheets/locomotive/new/_sidebar.scss +4 -0
  26. data/app/assets/stylesheets/locomotive/old/_list.scss +35 -0
  27. data/app/assets/stylesheets/locomotive/old/_main.scss +6 -6
  28. data/app/controllers/locomotive/concerns/authorization_controller.rb +4 -2
  29. data/app/controllers/locomotive/content_entries_controller.rb +6 -0
  30. data/app/controllers/locomotive/content_entry_impersonations_controller.rb +11 -0
  31. data/app/controllers/locomotive/current_site_controller.rb +0 -1
  32. data/app/controllers/locomotive/dashboard_controller.rb +2 -0
  33. data/app/helpers/locomotive/dashboard_helper.rb +0 -101
  34. data/app/helpers/locomotive/shared/activities_helper.rb +106 -0
  35. data/app/helpers/locomotive/shared/site_metafields_helper.rb +1 -1
  36. data/app/mailers/locomotive/notifications.rb +8 -0
  37. data/app/models/locomotive/account.rb +1 -0
  38. data/app/models/locomotive/concerns/site/cache.rb +2 -0
  39. data/app/models/locomotive/concerns/site/locales.rb +1 -0
  40. data/app/models/locomotive/content_type.rb +8 -7
  41. data/app/models/locomotive/membership.rb +1 -1
  42. data/app/models/locomotive/page.rb +2 -0
  43. data/app/models/locomotive/section.rb +1 -1
  44. data/app/policies/locomotive/account_policy.rb +1 -1
  45. data/app/policies/locomotive/content_asset_policy.rb +11 -3
  46. data/app/policies/locomotive/content_entry_policy.rb +11 -3
  47. data/app/policies/locomotive/page_policy.rb +16 -5
  48. data/app/policies/locomotive/site_policy.rb +18 -4
  49. data/app/policies/locomotive/translation_policy.rb +12 -4
  50. data/app/views/locomotive/content_entries/form/_actions.html.slim +12 -1
  51. data/app/views/locomotive/content_entries/form/_advanced.html.slim +1 -1
  52. data/app/views/locomotive/content_entries/index.html.slim +25 -17
  53. data/app/views/locomotive/current_site/form/_advanced.html.slim +6 -1
  54. data/app/views/locomotive/current_site/form/_url_redirections.html.slim +9 -3
  55. data/app/views/locomotive/layouts/account.html.slim +1 -33
  56. data/app/views/locomotive/pages/form/_main.html.slim +5 -2
  57. data/app/views/locomotive/shared/_head.html.slim +1 -1
  58. data/app/views/locomotive/shared/account/_head.html.slim +33 -0
  59. data/app/views/locomotive/shared/account/_navigation.html.slim +2 -1
  60. data/app/views/locomotive/sites/index.html.slim +4 -3
  61. data/config/locales/en.yml +7 -5
  62. data/config/locales/fr.yml +2 -0
  63. data/config/locales/simple_form.en.yml +3 -0
  64. data/config/webpack/production.js +1 -1
  65. data/lib/generators/locomotive/install/install_generator.rb +15 -2
  66. data/lib/generators/locomotive/install/templates/README +1 -1
  67. data/lib/generators/locomotive/install/templates/mongoid_heroku.yml +1 -1
  68. data/lib/locomotive/steam/middlewares/missing_translations.rb +3 -0
  69. data/lib/locomotive/steam/middlewares/page_editing.rb +7 -0
  70. data/lib/locomotive/steam/services/liquid_parser_with_cache_service.rb +22 -15
  71. data/lib/locomotive/steam_adaptor.rb +1 -1
  72. data/lib/locomotive/version.rb +1 -1
  73. data/lib/tasks/development_tasks.rake +7 -3
  74. data/lib/tasks/locomotive_tasks.rake +10 -0
  75. metadata +43 -16
  76. data/config/initializers/rails_fixes.rb +0 -16
  77. data/lib/locomotive/steam/middlewares/cache.rb +0 -69
@@ -28,6 +28,8 @@ module Locomotive
28
28
  field :locales, type: Array
29
29
  field :published, type: Boolean, default: false
30
30
  field :cache_enabled, type: Boolean, default: true
31
+ field :cache_control
32
+ field :cache_vary
31
33
  field :response_type, default: 'text/html'
32
34
  field :display_settings, type: Hash
33
35
 
@@ -76,7 +76,7 @@ module Locomotive
76
76
  properties: {
77
77
  id: { type: 'string' },
78
78
  label: { '$ref': '#/definitions/locale_string' },
79
- type: { enum: ['text', 'image_picker', 'checkbox', 'select', 'url', 'radio', 'content_type', 'hint'] },
79
+ type: { enum: ['text', 'image_picker', 'checkbox', 'select', 'url', 'radio', 'content_type', 'hint', 'integer'] },
80
80
  default: {}
81
81
  },
82
82
  required: [:id, :type]
@@ -15,7 +15,7 @@ module Locomotive
15
15
  end
16
16
 
17
17
  def update?
18
- super_admin? || owner?
18
+ (super_admin? || owner?) && !@resource.visitor?
19
19
  end
20
20
 
21
21
  def destroy?
@@ -5,16 +5,24 @@ module Locomotive
5
5
  site_staff?
6
6
  end
7
7
 
8
- def create?
8
+ def new?
9
9
  site_staff?
10
10
  end
11
11
 
12
- def update?
12
+ def edit?
13
13
  site_staff?
14
14
  end
15
15
 
16
+ def create?
17
+ site_staff? && !membership.visitor?
18
+ end
19
+
20
+ def update?
21
+ site_staff? && !membership.visitor?
22
+ end
23
+
16
24
  def destroy?
17
- site_staff?
25
+ site_staff? && !membership.visitor?
18
26
  end
19
27
 
20
28
  end
@@ -5,16 +5,24 @@ module Locomotive
5
5
  site_staff?
6
6
  end
7
7
 
8
- def create?
8
+ def new?
9
9
  site_staff?
10
10
  end
11
11
 
12
- def update?
12
+ def edit?
13
13
  site_staff?
14
14
  end
15
15
 
16
+ def create?
17
+ site_staff? && !membership.visitor?
18
+ end
19
+
20
+ def update?
21
+ site_staff? && !membership.visitor?
22
+ end
23
+
16
24
  def destroy?
17
- site_staff?
25
+ site_staff? && !membership.visitor?
18
26
  end
19
27
 
20
28
  end
@@ -5,16 +5,24 @@ module Locomotive
5
5
  site_staff?
6
6
  end
7
7
 
8
- def create?
8
+ def new?
9
9
  site_staff?
10
10
  end
11
11
 
12
- def update?
12
+ def edit?
13
13
  site_staff?
14
14
  end
15
15
 
16
+ def create?
17
+ site_staff? && !membership.visitor?
18
+ end
19
+
20
+ def update?
21
+ site_staff? && !membership.visitor?
22
+ end
23
+
16
24
  def destroy?
17
- site_staff? && !@resource.index_or_not_found?
25
+ site_staff? && !@resource.index_or_not_found? && !membership.visitor?
18
26
  end
19
27
 
20
28
  def show?
@@ -22,8 +30,11 @@ module Locomotive
22
30
  end
23
31
 
24
32
  def permitted_attributes
25
- attributes = [:title, :layout_id, :slug, :parent_id, :listed, :published, :redirect, :redirect_url, :redirect_type, :seo_title, :meta_description, :meta_keywords, :cache_enabled]
26
- attributes += [:handle] if site_admin_or_designer?
33
+ attributes = [:title, :layout_id, :slug, :parent_id, :listed, :published, :redirect, :redirect_url, :redirect_type, :seo_title, :meta_description, :meta_keywords]
34
+ if site_admin_or_designer?
35
+ attributes += [:cache_enabled, :cache_control, :cache_vary]
36
+ attributes += [:handle]
37
+ end
27
38
  attributes
28
39
  end
29
40
 
@@ -21,12 +21,20 @@ module Locomotive
21
21
  true
22
22
  end
23
23
 
24
+ def edit?
25
+ super_admin? || site_staff?
26
+ end
27
+
28
+ def new
29
+ !account.visitor?
30
+ end
31
+
24
32
  def create?
25
- true
33
+ !account.visitor?
26
34
  end
27
35
 
28
36
  def update?
29
- super_admin? || site_staff?
37
+ super_admin? || site_staff? && !membership.visitor?
30
38
  end
31
39
 
32
40
  def destroy?
@@ -46,11 +54,17 @@ module Locomotive
46
54
  end
47
55
 
48
56
  def permitted_attributes
49
- plain = [:name, :handle, :picture, :remove_picture, :seo_title, :meta_keywords, :meta_description, :timezone_name, :robots_txt, :asset_host, :cache_enabled, :redirect_to_first_domain, :redirect_to_https, :private_access, :password, :prefix_default_locale]
57
+ plain = [
58
+ :name, :handle, :picture, :remove_picture, :seo_title, :meta_keywords, :meta_description, :robots_txt,
59
+ :timezone_name, :timezone,
60
+ :cache_enabled, :cache_control, :cache_vary,
61
+ :asset_host, :redirect_to_first_domain, :redirect_to_https,
62
+ :private_access, :password, :prefix_default_locale, :bypass_browser_locale
63
+ ]
50
64
  hash = { domains: [], locales: [], url_redirections: [] }
51
65
 
52
66
  if persisted? && !update_advanced?
53
- plain -= [:timezone_name, :robots_txt, :cache_enabled, :prefix_default_locale, :asset_host]
67
+ plain -= [:timezone_name, :timezone, :robots_txt, :cache_enabled, :cache_control, :cache_vary, :prefix_default_locale, :bypass_browser_locale, :asset_host]
54
68
  hash.delete(:locales)
55
69
  hash.delete(:url_redirections)
56
70
  end
@@ -5,20 +5,28 @@ module Locomotive
5
5
  site_staff?
6
6
  end
7
7
 
8
- def create?
8
+ def new?
9
9
  site_staff?
10
10
  end
11
11
 
12
- def update?
12
+ def edit?
13
13
  site_staff?
14
14
  end
15
15
 
16
+ def create?
17
+ site_staff? && !membership.visitor?
18
+ end
19
+
20
+ def update?
21
+ site_staff? && !membership.visitor?
22
+ end
23
+
16
24
  def destroy?
17
- site_staff?
25
+ site_staff? && !membership.visitor?
18
26
  end
19
27
 
20
28
  def destroy_all?
21
- site_staff?
29
+ site_staff? && !membership.visitor?
22
30
  end
23
31
 
24
32
  end
@@ -1 +1,12 @@
1
- = f.actions back_url: content_entries_path(current_site, @content_type.slug), use_stored_location: params[:_location].present?
1
+ - if defined?(advanced) && advanced == true && @content_entry.persisted?
2
+ = f.actions do
3
+ .row
4
+ .col-sm-6.text-left
5
+ - if policy(@content_entry).destroy?
6
+ = link_to t(:delete, scope: 'simple_form.buttons.locomotive.content_entry'), content_entry_path(current_site, @content_type.slug, @content_entry), data: { confirm: I18n.t('locomotive.messages.confirm') }, class:'btn btn-sm btn-danger', method: :delete
7
+
8
+ .col-sm-6.text-right
9
+ = f.actions_with_back_button back_url: content_entries_path(current_site, @content_type.slug), use_stored_location: params[:_location].present?
10
+
11
+ - else
12
+ = f.actions back_url: content_entries_path(current_site, @content_type.slug), use_stored_location: params[:_location].present?
@@ -2,4 +2,4 @@
2
2
  = f.input :_slug, required: false
3
3
  = f.input :_visible, as: :toggle
4
4
 
5
- = render 'locomotive/content_entries/form/actions', f: f
5
+ = render 'locomotive/content_entries/form/actions', f: f, advanced: true
@@ -14,30 +14,36 @@
14
14
  = t('.bulk_destroy')
15
15
 
16
16
  .main-action
17
- .btn-group
17
+ - if can_edit_public_submission_accounts?(@content_type) || !empty_collection?(@content_entries)
18
+ .btn-group
19
+ = link_to new_content_entry_path(current_site, @content_type.slug), class: 'btn btn-primary btn-sm' do
20
+ i.fa.fa-plus
21
+ |  
22
+ = t('.new')
23
+ button.btn.btn-primary.btn-sm.dropdown-toggle data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"
24
+ span.caret
25
+ span.sr-only Toggle Dropdown
26
+ ul.dropdown-menu.dropdown-menu-right
27
+ - if can_edit_public_submission_accounts?(@content_type)
28
+ li
29
+ = link_to edit_public_submission_accounts_path(current_site, @content_type.slug) do
30
+ i.fas.fa-cog
31
+ = t('.edit_notification_settings')
32
+
33
+ - unless empty_collection?(@content_entries)
34
+ li
35
+ = link_to export_content_entries_path(current_site, @content_type.slug, :csv) do
36
+ i.fa.fa-download
37
+ = t('.download')
38
+ - else
18
39
  = link_to new_content_entry_path(current_site, @content_type.slug), class: 'btn btn-primary btn-sm' do
19
40
  i.fa.fa-plus
20
41
  |  
21
42
  = t('.new')
22
- button.btn.btn-primary.btn-sm.dropdown-toggle data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"
23
- span.caret
24
- span.sr-only Toggle Dropdown
25
- ul.dropdown-menu.dropdown-menu-right
26
- - if can_edit_public_submission_accounts?(@content_type)
27
- li
28
- = link_to edit_public_submission_accounts_path(current_site, @content_type.slug) do
29
- i.fas.fa-cog
30
- = t('.edit_notification_settings')
31
-
32
- - unless empty_collection?(@content_entries)
33
- li
34
- = link_to export_content_entries_path(current_site, @content_type.slug, :csv) do
35
- i.fa.fa-download
36
- = t('.download')
37
43
 
38
44
  - if @content_type.groupable?
39
45
  .row.list-groups
40
- .nav-container
46
+ .nav-container.nav-container--scroll
41
47
  ul.nav.nav-tabs role='tablist'
42
48
  li class="#{'active' if params[:group].nil?}"
43
49
  = link_to t('.group_by.all'), content_entries_path(current_site, @content_type.slug, query: params[:query])
@@ -46,6 +52,8 @@
46
52
  li class="#{'active' if params[:group] == group[:name]}"
47
53
  = link_to group[:name], group[:url]
48
54
 
55
+ li
56
+
49
57
  .row.list-header
50
58
  .col.col-md-6.text-left
51
59
  - if @content_type.filter_fields.present?
@@ -3,11 +3,16 @@
3
3
 
4
4
  = f.input :prefix_default_locale, as: :toggle
5
5
 
6
+ = f.input :bypass_browser_locale, as: :toggle
7
+
6
8
  = f.input :timezone_name, as: :select, include_blank: false, collection: options_for_site_timezones
7
9
 
8
10
  = f.input :robots_txt, as: :code, wrapper_html: { class: 'small' }
9
11
 
10
- = f.input :cache_enabled, as: :toggle
12
+ = f.inputs :cache_enabled do
13
+ = f.input :cache_enabled, as: :toggle
14
+ = f.input :cache_control, as: :string, wrapper_html: { class: "#{'hide' unless f.object.cache_enabled?}" }
15
+ = f.input :cache_vary, as: :string, wrapper_html: { class: "#{'hide' unless f.object.cache_enabled?}" }
11
16
 
12
17
  - if policy(@site).destroy?
13
18
  = f.actions do
@@ -1,9 +1,15 @@
1
1
  = f.inputs :url_redirections do
2
- = f.input :url_redirections_expert_mode, as: :toggle
3
2
 
4
- = f.input :url_redirections_plain_text, as: :text, wrapper_html: { class: 'hide' }, input_html: { rows: 30 }
3
+ - if f.object.url_redirections.count > 30
4
+ = f.hidden_field :url_redirections_expert_mode, value: '1'
5
+ = f.input :url_redirections_plain_text, as: :text, input_html: { rows: 30 }
6
+ - else
7
+ = f.input :url_redirections_expert_mode, as: :toggle
8
+
9
+ = f.input :url_redirections_plain_text, as: :text, wrapper_html: { class: 'hide' }, input_html: { rows: 30 }
10
+
11
+ = f.input :url_redirections, as: :array, hint: t(:url_redirections, scope: 'simple_form.hints.locomotive.site').html_safe, placeholder: true, collection: f.object.url_redirections_with_information(false).to_a, template: :url_redirection, template_url: new_url_redirection_current_site_path(current_site)
5
12
 
6
- = f.input :url_redirections, as: :array, hint: t(:url_redirections, scope: 'simple_form.hints.locomotive.site').html_safe, placeholder: true, collection: f.object.url_redirections_with_information(false).to_a, template: :url_redirection, template_url: new_url_redirection_current_site_path(current_site)
7
13
 
8
14
  = f.actions do
9
15
  = f.action
@@ -1,39 +1,7 @@
1
1
  doctype html
2
2
  html xmlns='http://www.w3.org/1999/xhtml' lang=I18n.locale
3
3
  head
4
- meta charset="utf-8"
5
- meta http-equiv="x-ua-compatible" content="ie=edge"
6
-
7
- title= escape_once(strip_tags(title) + " | #{application_name}")
8
-
9
- meta name="viewport" content="width=device-width, initial-scale=1"
10
-
11
- link rel="icon" type="image/png" href="#{asset_url('locomotive/favicon.png')}" sizes="32x32"
12
-
13
- link href="https://fonts.googleapis.com/css?family=Muli:400,300|Noto+Sans:400,700" rel="stylesheet" type="text/css"
14
-
15
- javascript:
16
- window.Locomotive = { mounted_on: '#{Locomotive.mounted_on}' }
17
-
18
- = javascript_include_tag 'locomotive'
19
- = stylesheet_link_tag 'locomotive/account', media: 'screen'
20
-
21
- javascript:
22
- window.locale = '#{locale}';
23
-
24
- $(document).ready(function() {
25
-
26
- window.application_view = new Locomotive.Views.SimpleView({
27
- flash: #{{flash_messages_to_json}},
28
- view: #{backbone_view_class_name}
29
- });
30
- window.application_view.render();
31
-
32
- });
33
-
34
- = csrf_meta_tag
35
-
36
- = yield :head
4
+ = render 'locomotive/shared/account/head'
37
5
 
38
6
  body class=[controller.controller_name, controller.action_name, flash.empty? ? '' : 'with-flash'].join(' ')
39
7
  .public-background
@@ -26,7 +26,10 @@
26
26
 
27
27
  = f.input :listed, as: :toggle
28
28
 
29
- - if current_site.cache_enabled? && !@page.redirect?
30
- = f.input :cache_enabled, as: :toggle
29
+ - if policy(current_site).site_admin_or_designer? && current_site.cache_enabled? && !@page.redirect?
30
+ = f.inputs :cache_enabled do
31
+ = f.input :cache_enabled, as: :toggle
32
+ = f.input :cache_control, as: :string, wrapper_html: { class: "#{'hide' unless f.object.cache_enabled?}" }
33
+ = f.input :cache_vary, as: :string, wrapper_html: { class: "#{'hide' unless f.object.cache_enabled?}" }
31
34
 
32
35
  = render 'locomotive/pages/form/actions', f: f
@@ -1,5 +1,5 @@
1
1
  - if current_site
2
- title== escape_once("#{Locomotive.config.name} — #{current_site.name}")
2
+ title== escape_once("#{current_site.name} — #{Locomotive.config.name}")
3
3
  - else
4
4
  title= escape_once(Locomotive.config.name)
5
5
 
@@ -0,0 +1,33 @@
1
+ meta charset="utf-8"
2
+ meta http-equiv="x-ua-compatible" content="ie=edge"
3
+
4
+ title= escape_once(strip_tags(title) + " | #{application_name}")
5
+
6
+ meta name="viewport" content="width=device-width, initial-scale=1"
7
+
8
+ link rel="icon" type="image/png" href="#{asset_url('locomotive/favicon.png')}" sizes="32x32"
9
+
10
+ link href="https://fonts.googleapis.com/css?family=Muli:400,300|Noto+Sans:400,700" rel="stylesheet" type="text/css"
11
+
12
+ javascript:
13
+ window.Locomotive = { mounted_on: '#{Locomotive.mounted_on}' }
14
+
15
+ = javascript_include_tag 'locomotive'
16
+ = stylesheet_link_tag 'locomotive/account', media: 'screen'
17
+
18
+ javascript:
19
+ window.locale = '#{locale}';
20
+
21
+ $(document).ready(function() {
22
+
23
+ window.application_view = new Locomotive.Views.SimpleView({
24
+ flash: #{{flash_messages_to_json}},
25
+ view: #{backbone_view_class_name}
26
+ });
27
+ window.application_view.render();
28
+
29
+ });
30
+
31
+ = csrf_meta_tag
32
+
33
+ = yield :head
@@ -7,7 +7,8 @@ ul.navigation-links
7
7
 
8
8
  ul.dropdown-menu role='menu' aria-labelledby="navigation-dropdown"
9
9
  li= link_to t(:sites, scope: 'locomotive.shared.header'), sites_path
10
- li= link_to t(:account, scope: 'locomotive.shared.header'), edit_my_account_path(_location: request.fullpath)
10
+ - if policy(current_locomotive_account).edit?
11
+ li= link_to t(:account, scope: 'locomotive.shared.header'), edit_my_account_path(_location: request.fullpath)
11
12
  li= link_to t(:help, scope: 'locomotive.shared.header'), 'http://locomotive-v3.readme.io', target: '_blank'
12
13
  li class="divider"
13
14
  li= link_to t(:logout, scope: 'locomotive.shared.header'), sign_out_path, data: { method: 'delete' }
@@ -11,6 +11,7 @@
11
11
  .public-entries
12
12
  = render @sites
13
13
 
14
- = link_to new_site_url, class: 'public-entry is-add' do
15
- i.fa.fa-plus
16
- = t('.new')
14
+ - if policy(Locomotive::Site).new?
15
+ = link_to new_site_url, class: 'public-entry is-add' do
16
+ i.fa.fa-plus
17
+ = t('.new')