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.
- checksums.yaml +4 -4
- data/MIT-LICENSE +1 -1
- data/README.md +1 -1
- data/Rakefile +0 -6
- data/app/api/locomotive/api/entities/site_entity.rb +1 -1
- data/app/api/locomotive/api/forms/content_type_form.rb +1 -0
- data/app/api/locomotive/api/forms/page_form.rb +2 -1
- data/app/api/locomotive/api/forms/site_form.rb +7 -1
- data/app/api/locomotive/api/helpers/persistence_helper.rb +3 -0
- data/app/api/locomotive/api/resources/account_resource.rb +15 -3
- data/app/api/locomotive/api/resources/content_type_resource.rb +3 -0
- data/app/api/locomotive/api/resources/membership_resource.rb +1 -1
- data/app/api/locomotive/api/resources/site_resource.rb +6 -0
- data/app/assets/javascripts/locomotive/editor.js +1311 -703
- data/app/assets/javascripts/locomotive/views/content_entries/edit_view.js.coffee +5 -0
- data/app/assets/javascripts/locomotive/views/content_entries/index_view.js.coffee +1 -0
- data/app/assets/javascripts/locomotive/views/content_entries/new_view.js.coffee +4 -0
- data/app/assets/javascripts/locomotive/views/current_site/edit_view.js.coffee +6 -0
- data/app/assets/javascripts/locomotive/views/page_content/edit_view.js.coffee +1 -0
- data/app/assets/javascripts/locomotive/views/pages/_form_view.js.coffee +6 -0
- data/app/assets/javascripts/locomotive/views/pages/edit_view.js.coffee +4 -0
- data/app/assets/javascripts/locomotive/views/pages/list_view.js.coffee +5 -0
- data/app/assets/javascripts/locomotive/views/pages/new_view.js.coffee +4 -0
- data/app/assets/stylesheets/locomotive/editor.css +390 -127
- data/app/assets/stylesheets/locomotive/new/_sidebar.scss +4 -0
- data/app/assets/stylesheets/locomotive/old/_list.scss +35 -0
- data/app/assets/stylesheets/locomotive/old/_main.scss +6 -6
- data/app/controllers/locomotive/concerns/authorization_controller.rb +4 -2
- data/app/controllers/locomotive/content_entries_controller.rb +6 -0
- data/app/controllers/locomotive/content_entry_impersonations_controller.rb +11 -0
- data/app/controllers/locomotive/current_site_controller.rb +0 -1
- data/app/controllers/locomotive/dashboard_controller.rb +2 -0
- data/app/helpers/locomotive/dashboard_helper.rb +0 -101
- data/app/helpers/locomotive/shared/activities_helper.rb +106 -0
- data/app/helpers/locomotive/shared/site_metafields_helper.rb +1 -1
- data/app/mailers/locomotive/notifications.rb +8 -0
- data/app/models/locomotive/account.rb +1 -0
- data/app/models/locomotive/concerns/site/cache.rb +2 -0
- data/app/models/locomotive/concerns/site/locales.rb +1 -0
- data/app/models/locomotive/content_type.rb +8 -7
- data/app/models/locomotive/membership.rb +1 -1
- data/app/models/locomotive/page.rb +2 -0
- data/app/models/locomotive/section.rb +1 -1
- data/app/policies/locomotive/account_policy.rb +1 -1
- data/app/policies/locomotive/content_asset_policy.rb +11 -3
- data/app/policies/locomotive/content_entry_policy.rb +11 -3
- data/app/policies/locomotive/page_policy.rb +16 -5
- data/app/policies/locomotive/site_policy.rb +18 -4
- data/app/policies/locomotive/translation_policy.rb +12 -4
- data/app/views/locomotive/content_entries/form/_actions.html.slim +12 -1
- data/app/views/locomotive/content_entries/form/_advanced.html.slim +1 -1
- data/app/views/locomotive/content_entries/index.html.slim +25 -17
- data/app/views/locomotive/current_site/form/_advanced.html.slim +6 -1
- data/app/views/locomotive/current_site/form/_url_redirections.html.slim +9 -3
- data/app/views/locomotive/layouts/account.html.slim +1 -33
- data/app/views/locomotive/pages/form/_main.html.slim +5 -2
- data/app/views/locomotive/shared/_head.html.slim +1 -1
- data/app/views/locomotive/shared/account/_head.html.slim +33 -0
- data/app/views/locomotive/shared/account/_navigation.html.slim +2 -1
- data/app/views/locomotive/sites/index.html.slim +4 -3
- data/config/locales/en.yml +7 -5
- data/config/locales/fr.yml +2 -0
- data/config/locales/simple_form.en.yml +3 -0
- data/config/webpack/production.js +1 -1
- data/lib/generators/locomotive/install/install_generator.rb +15 -2
- data/lib/generators/locomotive/install/templates/README +1 -1
- data/lib/generators/locomotive/install/templates/mongoid_heroku.yml +1 -1
- data/lib/locomotive/steam/middlewares/missing_translations.rb +3 -0
- data/lib/locomotive/steam/middlewares/page_editing.rb +7 -0
- data/lib/locomotive/steam/services/liquid_parser_with_cache_service.rb +22 -15
- data/lib/locomotive/steam_adaptor.rb +1 -1
- data/lib/locomotive/version.rb +1 -1
- data/lib/tasks/development_tasks.rake +7 -3
- data/lib/tasks/locomotive_tasks.rake +10 -0
- metadata +43 -16
- data/config/initializers/rails_fixes.rb +0 -16
- data/lib/locomotive/steam/middlewares/cache.rb +0 -69
@@ -6,6 +6,41 @@
|
|
6
6
|
.list-groups {
|
7
7
|
margin-bottom: 10px;
|
8
8
|
|
9
|
+
.nav-container.nav-container--scroll {
|
10
|
+
padding-left: 15px;
|
11
|
+
padding-right: 15px;
|
12
|
+
|
13
|
+
.nav-tabs {
|
14
|
+
position: relative;
|
15
|
+
display: flex;
|
16
|
+
flex-wrap: nowrap;
|
17
|
+
overflow: auto;
|
18
|
+
-webkit-overflow-scrolling: touch;
|
19
|
+
-ms-overflow-style: -ms-autohiding-scrollbar;
|
20
|
+
border: none;
|
21
|
+
padding-left: 0px;
|
22
|
+
padding-right: 0px;
|
23
|
+
padding-bottom: 2px;
|
24
|
+
|
25
|
+
// don't display the scrollbar
|
26
|
+
&::-webkit-scrollbar { display: none; }
|
27
|
+
|
28
|
+
& > li {
|
29
|
+
flex: 0 0 auto;
|
30
|
+
z-index: 2;
|
31
|
+
|
32
|
+
&:last-child {
|
33
|
+
width: 9999px;
|
34
|
+
height: 2px;
|
35
|
+
border-bottom: 2px solid #ccc;
|
36
|
+
position: absolute;
|
37
|
+
bottom: 2px;
|
38
|
+
z-index: 1;
|
39
|
+
}
|
40
|
+
}
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
9
44
|
.nav-tabs {
|
10
45
|
padding-left: 15px;
|
11
46
|
padding-right: 15px;
|
@@ -16,6 +16,12 @@
|
|
16
16
|
color: rgba($main_title_color, 0.7);
|
17
17
|
}
|
18
18
|
|
19
|
+
.dropdown-menu {
|
20
|
+
i {
|
21
|
+
margin-right: 1rem;
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
19
25
|
.actions {
|
20
26
|
text-align: right;
|
21
27
|
|
@@ -31,12 +37,6 @@
|
|
31
37
|
.btn.dropdown-toggle {
|
32
38
|
border-left: 1px solid $btn-primary-border;
|
33
39
|
}
|
34
|
-
|
35
|
-
.dropdown-menu {
|
36
|
-
i {
|
37
|
-
margin-right: 1rem;
|
38
|
-
}
|
39
|
-
}
|
40
40
|
}
|
41
41
|
}
|
42
42
|
}
|
@@ -14,10 +14,12 @@ module Locomotive
|
|
14
14
|
def render_access_denied(exception)
|
15
15
|
::Locomotive.log "[AccessDenied] #{exception.inspect}"
|
16
16
|
|
17
|
+
message = I18n.t('locomotive.errors.access_denied.message')
|
18
|
+
|
17
19
|
if request.xhr?
|
18
|
-
render json: { error:
|
20
|
+
render json: { error: message }, status: 401, layout: false
|
19
21
|
else
|
20
|
-
flash[:alert] =
|
22
|
+
flash[:alert] = message
|
21
23
|
redirect_to current_site? ? dashboard_path(current_site) : sites_path
|
22
24
|
end
|
23
25
|
end
|
@@ -80,6 +80,12 @@ module Locomotive
|
|
80
80
|
respond_with @content_type, location: content_entries_path(current_site, @content_type.slug, default_location_params)
|
81
81
|
end
|
82
82
|
|
83
|
+
def destroy
|
84
|
+
authorize @content_entry
|
85
|
+
service.bulk_destroy([*params[:id]])
|
86
|
+
respond_with @content_type, location: content_entries_path(current_site, @content_type.slug, default_location_params)
|
87
|
+
end
|
88
|
+
|
83
89
|
private
|
84
90
|
|
85
91
|
def load_content_type
|
@@ -12,6 +12,8 @@ module Locomotive
|
|
12
12
|
# add a flag to notify that the sign in was done by impersonating the entry
|
13
13
|
session[:authenticated_impersonation] = '1'
|
14
14
|
|
15
|
+
# notify signed in
|
16
|
+
notify(:signed_in, content_entry, request)
|
15
17
|
redirect_to preview_url(current_site)
|
16
18
|
else
|
17
19
|
redirect_to content_entries_path(current_site, content_type.slug)
|
@@ -28,5 +30,14 @@ module Locomotive
|
|
28
30
|
@content_entry ||= content_type.entries.find(params[:content_entry_id])
|
29
31
|
end
|
30
32
|
|
33
|
+
def notify(action, entry, request)
|
34
|
+
ActiveSupport::Notifications.instrument("steam.auth.#{action}",
|
35
|
+
site: current_site,
|
36
|
+
entry: entry,
|
37
|
+
locale: locale,
|
38
|
+
request: request
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
31
42
|
end
|
32
43
|
end
|
@@ -12,106 +12,5 @@ module Locomotive
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
# Activity
|
16
|
-
|
17
|
-
def activity_to_icon(activity)
|
18
|
-
case activity.domain
|
19
|
-
when 'site' then 'fa-cog'
|
20
|
-
when 'page' then 'fa-file-alt'
|
21
|
-
when 'page_content' then 'fa-file-alt'
|
22
|
-
when 'editable_element' then 'fa-file-alt'
|
23
|
-
when 'content_entry' then activity.action == 'created_public' ? 'fa-comment' : 'fa-archive'
|
24
|
-
when 'content_asset' then 'fa-image'
|
25
|
-
when 'membership' then 'fa-user'
|
26
|
-
when 'site_metafields' then current_site_metafields_ui[:icon]
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def render_activity_sentence(activity)
|
31
|
-
params = activity.parameters
|
32
|
-
locale = activity.locale
|
33
|
-
|
34
|
-
options = case activity.key
|
35
|
-
when /\Apage\./ then activity_page_options(params)
|
36
|
-
when /\Acontent_entry\./ then activity_content_entry_options(params, locale)
|
37
|
-
when 'page_content.updated' then activity_page_content_options(params, locale)
|
38
|
-
when 'editable_element.updated_bulk' then activity_bulk_editable_elements_options(params)
|
39
|
-
when 'content_asset.created_bulk' then { count: activity_emphasize(params[:assets].size) }
|
40
|
-
when 'content_asset.destroyed' then { name: activity_emphasize(params[:name]) }
|
41
|
-
when 'membership.created' then { name: activity_emphasize(params[:name]) }
|
42
|
-
when 'site_metafields.updated' then { label: current_site_metafields_ui[:label].downcase }
|
43
|
-
end
|
44
|
-
|
45
|
-
activity_key_to_sentence(activity.key, options)
|
46
|
-
end
|
47
|
-
|
48
|
-
def render_activity_additional_information(activity)
|
49
|
-
case activity.key
|
50
|
-
when 'content_asset.created_bulk' then activity_bulk_content_assets(activity.parameters)
|
51
|
-
# when 'editable_element.updated_bulk' then activity_bulk_editable_elements(activity.parameters)
|
52
|
-
else nil
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
def activity_key_to_sentence(key, options = nil)
|
57
|
-
I18n.t(key, (options || {}).merge(scope: 'locomotive.activity')).html_safe
|
58
|
-
end
|
59
|
-
|
60
|
-
def activity_emphasize(text)
|
61
|
-
content_tag(:strong, text)
|
62
|
-
end
|
63
|
-
|
64
|
-
def activity_page_options(params)
|
65
|
-
if params[:_id]
|
66
|
-
{ page: link_to(params[:title], editable_elements_path(current_site, params[:_id])) }
|
67
|
-
elsif params[:title]
|
68
|
-
{ page: activity_emphasize(params[:title]) }
|
69
|
-
else
|
70
|
-
nil
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
def activity_page_content_options(params, locale)
|
75
|
-
path = edit_page_content_path(current_site, params[:_id], content_locale: locale)
|
76
|
-
{ page: link_to(truncate(params[:title]), path).html_safe }
|
77
|
-
end
|
78
|
-
|
79
|
-
def activity_bulk_editable_elements_options(params)
|
80
|
-
pages = params[:pages].map do |page|
|
81
|
-
link_to truncate(page[:title]), editable_elements_path(current_site, page[:_id])
|
82
|
-
end.join(', ').html_safe
|
83
|
-
|
84
|
-
{ pages: pages }
|
85
|
-
end
|
86
|
-
|
87
|
-
def activity_content_entry_options(params, locale)
|
88
|
-
entry = if params[:_id]
|
89
|
-
path = edit_content_entry_path(current_site, params[:content_type_slug], params[:_id], content_locale: locale)
|
90
|
-
link_to(params[:label], path)
|
91
|
-
elsif params[:label]
|
92
|
-
activity_emphasize(params[:label])
|
93
|
-
elsif params[:labels]
|
94
|
-
activity_emphasize(params[:labels].join(', '))
|
95
|
-
else
|
96
|
-
nil
|
97
|
-
end
|
98
|
-
|
99
|
-
content_type = link_to(params[:content_type], content_entries_path(current_site, params[:content_type_slug]))
|
100
|
-
|
101
|
-
{ entry: entry, content_type: content_type }
|
102
|
-
end
|
103
|
-
|
104
|
-
def activity_bulk_content_assets(params)
|
105
|
-
list = params[:assets].map do |asset|
|
106
|
-
if asset[:image] && asset[:id] && current_site.content_assets.where(_id: asset[:id]).exists?
|
107
|
-
content_tag(:li, link_to(image_tag(Locomotive::Dragonfly.resize_url(asset[:url], '60x60#'), alt: asset[:name]), asset[:url]))
|
108
|
-
else
|
109
|
-
content_tag(:li, link_to(truncate(asset[:name], length: 20), asset[:url]))
|
110
|
-
end
|
111
|
-
end.join("\n").html_safe
|
112
|
-
|
113
|
-
content_tag(:ul, list, class: 'assets') + content_tag(:div, '', class: 'clearfix')
|
114
|
-
end
|
115
|
-
|
116
15
|
end
|
117
16
|
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
module Locomotive
|
2
|
+
module Shared
|
3
|
+
module ActivitiesHelper
|
4
|
+
|
5
|
+
def activity_to_icon(activity)
|
6
|
+
case activity.domain
|
7
|
+
when 'site' then 'fa-cog'
|
8
|
+
when 'page' then 'fa-file-alt'
|
9
|
+
when 'page_content' then 'fa-file-alt'
|
10
|
+
when 'editable_element' then 'fa-file-alt'
|
11
|
+
when 'content_entry' then activity.action == 'created_public' ? 'fa-comment' : 'fa-archive'
|
12
|
+
when 'content_asset' then 'fa-image'
|
13
|
+
when 'membership' then 'fa-user'
|
14
|
+
when 'site_metafields' then current_site_metafields_ui[:icon]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def render_activity_sentence(activity)
|
19
|
+
params = activity.parameters
|
20
|
+
locale = activity.locale
|
21
|
+
|
22
|
+
options = case activity.key
|
23
|
+
when /\Apage\./ then activity_page_options(params)
|
24
|
+
when /\Acontent_entry\./ then activity_content_entry_options(params, locale)
|
25
|
+
when 'page_content.updated' then activity_page_content_options(params, locale)
|
26
|
+
when 'editable_element.updated_bulk' then activity_bulk_editable_elements_options(params)
|
27
|
+
when 'content_asset.created_bulk' then { count: activity_emphasize(params[:assets].size) }
|
28
|
+
when 'content_asset.destroyed' then { name: activity_emphasize(params[:name]) }
|
29
|
+
when 'membership.created' then { name: activity_emphasize(params[:name]) }
|
30
|
+
when 'site_metafields.updated' then { label: current_site_metafields_ui[:label].downcase }
|
31
|
+
end
|
32
|
+
|
33
|
+
activity_key_to_sentence(activity.key, options)
|
34
|
+
end
|
35
|
+
|
36
|
+
def render_activity_additional_information(activity)
|
37
|
+
case activity.key
|
38
|
+
when 'content_asset.created_bulk' then activity_bulk_content_assets(activity.parameters)
|
39
|
+
# when 'editable_element.updated_bulk' then activity_bulk_editable_elements(activity.parameters)
|
40
|
+
else nil
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def activity_key_to_sentence(key, options = nil)
|
45
|
+
I18n.t(key, (options || {}).merge(scope: 'locomotive.activity')).html_safe
|
46
|
+
end
|
47
|
+
|
48
|
+
def activity_emphasize(text)
|
49
|
+
content_tag(:strong, text)
|
50
|
+
end
|
51
|
+
|
52
|
+
def activity_page_options(params)
|
53
|
+
if params[:_id]
|
54
|
+
{ page: link_to(params[:title], editable_elements_path(current_site, params[:_id])) }
|
55
|
+
elsif params[:title]
|
56
|
+
{ page: activity_emphasize(params[:title]) }
|
57
|
+
else
|
58
|
+
nil
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def activity_page_content_options(params, locale)
|
63
|
+
path = edit_page_content_path(current_site, params[:_id], content_locale: locale)
|
64
|
+
{ page: link_to(truncate(params[:title]), path).html_safe }
|
65
|
+
end
|
66
|
+
|
67
|
+
def activity_bulk_editable_elements_options(params)
|
68
|
+
pages = params[:pages].map do |page|
|
69
|
+
link_to truncate(page[:title]), editable_elements_path(current_site, page[:_id])
|
70
|
+
end.join(', ').html_safe
|
71
|
+
|
72
|
+
{ pages: pages }
|
73
|
+
end
|
74
|
+
|
75
|
+
def activity_content_entry_options(params, locale)
|
76
|
+
entry = if params[:_id]
|
77
|
+
path = edit_content_entry_path(current_site, params[:content_type_slug], params[:_id], content_locale: locale)
|
78
|
+
link_to(params[:label], path)
|
79
|
+
elsif params[:label]
|
80
|
+
activity_emphasize(params[:label])
|
81
|
+
elsif params[:labels]
|
82
|
+
activity_emphasize(params[:labels].join(', '))
|
83
|
+
else
|
84
|
+
nil
|
85
|
+
end
|
86
|
+
|
87
|
+
content_type = link_to(params[:content_type], content_entries_path(current_site, params[:content_type_slug]))
|
88
|
+
|
89
|
+
{ entry: entry, content_type: content_type }
|
90
|
+
end
|
91
|
+
|
92
|
+
def activity_bulk_content_assets(params)
|
93
|
+
list = params[:assets].map do |asset|
|
94
|
+
if asset[:image] && asset[:id] && current_site.content_assets.where(_id: asset[:id]).exists?
|
95
|
+
content_tag(:li, link_to(image_tag(Locomotive::Dragonfly.resize_url(asset[:url], '60x60#'), alt: asset[:name]), asset[:url]))
|
96
|
+
else
|
97
|
+
content_tag(:li, link_to(truncate(asset[:name], length: 20), asset[:url]))
|
98
|
+
end
|
99
|
+
end.join("\n").html_safe
|
100
|
+
|
101
|
+
content_tag(:ul, list, class: 'assets') + content_tag(:div, '', class: 'clearfix')
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -18,7 +18,7 @@ module Locomotive
|
|
18
18
|
ui[:hint] = current_site_metafields_ui_t(_ui['hint'], t('locomotive.current_site_metafields.index.help', default: ''))
|
19
19
|
|
20
20
|
# icon in the sidebar
|
21
|
-
ui[:icon] = "
|
21
|
+
ui[:icon] = "fas fa-#{_ui['icon'].present? ? _ui['icon'] : 'newspaper'}"
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
@@ -18,6 +18,14 @@ module Locomotive
|
|
18
18
|
Locomotive.config.mailer_sender
|
19
19
|
end)
|
20
20
|
|
21
|
+
# attach uploaded files
|
22
|
+
if @type.public_submission_email_attachments
|
23
|
+
entry.file_custom_fields.each do |name|
|
24
|
+
next if (file = entry.send(name)&.file).nil?
|
25
|
+
attachments[file.filename] = file.read
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
21
29
|
mail subject: subject, from: from, to: account.email, reply_to: from
|
22
30
|
end
|
23
31
|
|
@@ -26,6 +26,7 @@ module Locomotive
|
|
26
26
|
field :name
|
27
27
|
field :locale, default: Locomotive.config.default_locale.to_s or 'en'
|
28
28
|
field :super_admin, type: Boolean, default: false
|
29
|
+
field :visitor, type: Boolean, default: false
|
29
30
|
|
30
31
|
## validations ##
|
31
32
|
validates_presence_of :name
|
@@ -10,6 +10,7 @@ module Locomotive
|
|
10
10
|
## fields ##
|
11
11
|
field :locales, type: ::RawArray, default: []
|
12
12
|
field :prefix_default_locale, type: ::Boolean, default: false
|
13
|
+
field :bypass_browser_locale, type: ::Boolean, default: false
|
13
14
|
|
14
15
|
## validations ##
|
15
16
|
validate :can_not_remove_default_locale
|
@@ -20,17 +20,18 @@ module Locomotive
|
|
20
20
|
field :name
|
21
21
|
field :description
|
22
22
|
field :slug
|
23
|
-
field :label_field_id,
|
23
|
+
field :label_field_id, type: BSON::ObjectId
|
24
24
|
field :label_field_name
|
25
25
|
field :tree_parent_field_name
|
26
|
-
field :group_by_field_id,
|
26
|
+
field :group_by_field_id, type: BSON::ObjectId
|
27
27
|
field :order_by # either a BSON::ObjectId (field id) or a String (:_position, ...etc)
|
28
|
-
field :order_direction,
|
29
|
-
field :public_submission_enabled,
|
30
|
-
field :
|
31
|
-
field :public_submission_accounts,
|
28
|
+
field :order_direction, default: 'asc'
|
29
|
+
field :public_submission_enabled, type: Boolean, default: false
|
30
|
+
field :public_submission_email_attachments, type: Boolean, default: false
|
31
|
+
field :public_submission_accounts, type: Array, default: []
|
32
|
+
field :recaptcha_required, type: Boolean, default: false
|
32
33
|
field :number_of_entries
|
33
|
-
field :display_settings,
|
34
|
+
field :display_settings, type: Hash
|
34
35
|
|
35
36
|
## associations ##
|
36
37
|
has_many :entries, class_name: 'Locomotive::ContentEntry', dependent: :destroy
|