alchemy_cms 4.2.0.rc1 → 4.2.0
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.
Potentially problematic release.
This version of alchemy_cms might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.github/FUNDING.yml +4 -0
- data/.rubocop.yml +4 -0
- data/CHANGELOG.md +28 -3
- data/Gemfile +1 -1
- data/README.md +1 -1
- data/alchemy_cms.gemspec +5 -6
- data/app/assets/javascripts/alchemy/alchemy.dialog.js.coffee +3 -3
- data/app/assets/javascripts/alchemy/alchemy.elements_window.js.coffee +1 -1
- data/app/assets/stylesheets/alchemy/buttons.scss +15 -2
- data/app/assets/stylesheets/alchemy/dashboard.scss +2 -0
- data/app/assets/stylesheets/alchemy/elements.scss +129 -127
- data/app/assets/stylesheets/alchemy/frame.scss +9 -29
- data/app/assets/stylesheets/alchemy/navigation.scss +30 -6
- data/app/assets/stylesheets/alchemy/preview_window.scss +4 -0
- data/app/assets/stylesheets/alchemy/spinner.scss +1 -1
- data/app/controllers/alchemy/pages_controller.rb +9 -4
- data/app/helpers/alchemy/base_helper.rb +3 -4
- data/app/models/alchemy/element.rb +1 -1
- data/app/models/alchemy/page/page_scopes.rb +1 -1
- data/app/views/alchemy/admin/dashboard/index.html.erb +1 -1
- data/app/views/alchemy/admin/dashboard/info.html.erb +23 -22
- data/app/views/alchemy/admin/pages/edit.html.erb +10 -10
- data/app/views/alchemy/admin/resources/_form.html.erb +0 -8
- data/app/views/alchemy/admin/resources/_table_header.html.erb +2 -1
- data/app/views/alchemy/essences/_essence_select_editor.html.erb +1 -1
- data/config/locales/alchemy.en.yml +6 -1
- data/lib/alchemy/on_page_layout.rb +1 -1
- data/lib/alchemy/permissions.rb +5 -2
- data/lib/alchemy/resources_helper.rb +12 -10
- data/lib/alchemy/shell.rb +11 -3
- data/lib/alchemy/test_support/factories.rb +3 -1
- data/lib/alchemy/test_support/factories/attachment_factory.rb +2 -0
- data/lib/alchemy/test_support/factories/content_factory.rb +5 -0
- data/lib/alchemy/test_support/factories/dummy_user_factory.rb +2 -0
- data/lib/alchemy/test_support/factories/element_factory.rb +3 -0
- data/lib/alchemy/test_support/factories/essence_file_factory.rb +2 -0
- data/lib/alchemy/test_support/factories/essence_picture_factory.rb +2 -0
- data/lib/alchemy/test_support/factories/essence_text_factory.rb +2 -0
- data/lib/alchemy/test_support/factories/language_factory.rb +2 -0
- data/lib/alchemy/test_support/factories/page_factory.rb +2 -0
- data/lib/alchemy/test_support/factories/picture_factory.rb +2 -0
- data/lib/alchemy/test_support/factories/site_factory.rb +2 -0
- data/lib/alchemy/upgrader/four_point_one.rb +16 -16
- data/lib/alchemy/upgrader/four_point_two.rb +37 -20
- data/lib/alchemy/upgrader/tasks/cells_upgrader.rb +3 -2
- data/lib/alchemy/upgrader/tasks/element_partial_name_variable_updater.rb +28 -0
- data/lib/alchemy/upgrader/tasks/picture_gallery_upgrader.rb +34 -19
- data/lib/alchemy/version.rb +1 -1
- data/lib/tasks/alchemy/upgrade.rake +7 -1
- metadata +32 -14
- data/.teatro.yml +0 -8
@@ -42,18 +42,15 @@ div#overlay_text_box {
|
|
42
42
|
}
|
43
43
|
|
44
44
|
#header {
|
45
|
+
display: flex;
|
45
46
|
height: $header-height;
|
46
47
|
line-height: $header-height;
|
47
48
|
background: $header-background;
|
48
49
|
border-bottom: $default-border;
|
49
50
|
position: relative;
|
50
51
|
|
51
|
-
a {
|
52
|
-
|
53
|
-
|
54
|
-
&:hover {
|
55
|
-
text-decoration: none;
|
56
|
-
}
|
52
|
+
a:hover {
|
53
|
+
text-decoration: none;
|
57
54
|
}
|
58
55
|
|
59
56
|
.page_status_and_name {
|
@@ -76,8 +73,13 @@ div#overlay_text_box {
|
|
76
73
|
}
|
77
74
|
|
78
75
|
.page_name {
|
76
|
+
display: inline-block;
|
77
|
+
max-width: 100px;
|
79
78
|
margin-right: $default-margin;
|
80
79
|
line-height: $header-height;
|
80
|
+
white-space: nowrap;
|
81
|
+
overflow: hidden;
|
82
|
+
text-overflow: ellipsis;
|
81
83
|
}
|
82
84
|
}
|
83
85
|
|
@@ -96,12 +98,10 @@ div#overlay_text_box {
|
|
96
98
|
}
|
97
99
|
|
98
100
|
#user_info {
|
99
|
-
position: absolute;
|
100
|
-
top: 0;
|
101
|
-
right: 0;
|
102
101
|
height: $header-height;
|
103
102
|
font-size: $small-font-size;
|
104
103
|
padding-left: 2*$default-padding;
|
104
|
+
margin-left: auto;
|
105
105
|
border-bottom: $default-border;
|
106
106
|
background-color: $header-background;
|
107
107
|
|
@@ -126,23 +126,3 @@ div#overlay_text_box {
|
|
126
126
|
padding-right: 2*$default-padding;
|
127
127
|
}
|
128
128
|
}
|
129
|
-
|
130
|
-
#locked_pages {
|
131
|
-
|
132
|
-
label {
|
133
|
-
float: left;
|
134
|
-
font-size: $small-font-size;
|
135
|
-
line-height: 27px;
|
136
|
-
height: 27px;
|
137
|
-
margin-left: 8px;
|
138
|
-
margin-right: 4px;
|
139
|
-
}
|
140
|
-
|
141
|
-
img {
|
142
|
-
float: left;
|
143
|
-
}
|
144
|
-
|
145
|
-
.subnavi_tab > a {
|
146
|
-
padding-right: 0;
|
147
|
-
}
|
148
|
-
}
|
@@ -209,19 +209,42 @@
|
|
209
209
|
}
|
210
210
|
}
|
211
211
|
|
212
|
+
#locked_pages {
|
213
|
+
display: flex;
|
214
|
+
flex-grow: 1;
|
215
|
+
flex-wrap: nowrap;
|
216
|
+
height: $header-height;
|
217
|
+
|
218
|
+
label {
|
219
|
+
float: left;
|
220
|
+
font-size: $small-font-size;
|
221
|
+
line-height: 27px;
|
222
|
+
height: 27px;
|
223
|
+
margin-left: 8px;
|
224
|
+
margin-right: 4px;
|
225
|
+
}
|
226
|
+
|
227
|
+
img {
|
228
|
+
float: left;
|
229
|
+
}
|
230
|
+
|
231
|
+
.subnavi_tab > a {
|
232
|
+
padding-right: 0;
|
233
|
+
}
|
234
|
+
}
|
235
|
+
|
212
236
|
.locked_page {
|
213
|
-
|
214
|
-
|
237
|
+
display: flex;
|
238
|
+
flex-wrap: nowrap;
|
215
239
|
line-height: $header-height - 1;
|
216
240
|
color: #444;
|
217
241
|
border-right: $default-border;
|
218
242
|
border-bottom: $default-border;
|
219
|
-
padding-right: 24px;
|
220
243
|
|
221
244
|
form {
|
222
|
-
|
223
|
-
|
224
|
-
|
245
|
+
align-self: center;
|
246
|
+
justify-self: flex-end;
|
247
|
+
margin-right: $default-padding;
|
225
248
|
line-height: 1;
|
226
249
|
}
|
227
250
|
|
@@ -231,6 +254,7 @@
|
|
231
254
|
}
|
232
255
|
|
233
256
|
> a {
|
257
|
+
display: flex;
|
234
258
|
cursor: pointer;
|
235
259
|
padding: 0px 8px;
|
236
260
|
|
@@ -16,5 +16,9 @@
|
|
16
16
|
|
17
17
|
.collapsed-menu.elements-window-visible & {
|
18
18
|
width: calc(100vw - #{$collapsed-main-menu-width - $default-border-width} - #{$elements-window-width});
|
19
|
+
|
20
|
+
@media screen and (min-width: $large-screen-break-point) {
|
21
|
+
max-width: calc(100vw - #{$collapsed-main-menu-width - $default-border-width} - #{$elements-window-min-width});
|
22
|
+
}
|
19
23
|
}
|
20
24
|
}
|
@@ -155,10 +155,10 @@ module Alchemy
|
|
155
155
|
end
|
156
156
|
|
157
157
|
def set_expiration_headers
|
158
|
-
if
|
159
|
-
expires_in @page.expiration_time, public: !@page.restricted, must_revalidate: true
|
160
|
-
else
|
158
|
+
if must_not_cache?
|
161
159
|
expires_now
|
160
|
+
else
|
161
|
+
expires_in @page.expiration_time, public: !@page.restricted, must_revalidate: true
|
162
162
|
end
|
163
163
|
end
|
164
164
|
|
@@ -190,12 +190,17 @@ module Alchemy
|
|
190
190
|
# or the cache is stale, because it's been republished by the user.
|
191
191
|
#
|
192
192
|
def render_fresh_page?
|
193
|
-
|
193
|
+
must_not_cache? || stale?(etag: page_etag,
|
194
194
|
last_modified: @page.published_at,
|
195
195
|
public: !@page.restricted,
|
196
196
|
template: 'pages/show')
|
197
197
|
end
|
198
198
|
|
199
|
+
# don't cache pages if we have flash message to display or the page has caching disabled
|
200
|
+
def must_not_cache?
|
201
|
+
flash.present? || !@page.cache_page?
|
202
|
+
end
|
203
|
+
|
199
204
|
def page_not_found!
|
200
205
|
not_found_error!("Alchemy::Page not found \"#{request.fullpath}\"")
|
201
206
|
end
|
@@ -11,12 +11,11 @@ module Alchemy
|
|
11
11
|
# Logs a message in the Rails logger (warn level)
|
12
12
|
# and optionally displays an error message to the user.
|
13
13
|
def warning(message, text = nil)
|
14
|
-
Logger.warn(message, caller(
|
14
|
+
Logger.warn(message, caller(1..1))
|
15
15
|
unless text.nil?
|
16
|
-
|
17
|
-
|
16
|
+
render_message(:warning) do
|
17
|
+
text.html_safe
|
18
18
|
end
|
19
|
-
return warning
|
20
19
|
end
|
21
20
|
end
|
22
21
|
|
@@ -98,7 +98,7 @@ module Alchemy
|
|
98
98
|
scope :not_restricted, -> { joins(:page).merge(Page.not_restricted) }
|
99
99
|
scope :available, -> { published.not_trashed }
|
100
100
|
scope :named, ->(names) { where(name: names) }
|
101
|
-
scope :excluded, ->(names) { where(
|
101
|
+
scope :excluded, ->(names) { where.not(name: names) }
|
102
102
|
scope :fixed, -> { where(fixed: true) }
|
103
103
|
scope :unfixed, -> { where(fixed: false) }
|
104
104
|
scope :from_current_site, -> { where(Language.table_name => {site_id: Site.current || Site.default}).joins(page: 'language') }
|
@@ -66,7 +66,7 @@ module Alchemy
|
|
66
66
|
# Returns all content pages.
|
67
67
|
#
|
68
68
|
scope :contentpages, -> {
|
69
|
-
where(layoutpage: [false, nil]).where(
|
69
|
+
where(layoutpage: [false, nil]).where.not(parent_id: nil)
|
70
70
|
}
|
71
71
|
|
72
72
|
# Returns all public contentpages that are not locked.
|
@@ -1,6 +1,11 @@
|
|
1
|
-
<p class="center"
|
1
|
+
<p class="center">
|
2
|
+
<%= image_tag('alchemy/alchemy-logo.svg', width: 267, height: 91) %>
|
3
|
+
</p>
|
2
4
|
<h2 class="center">
|
3
|
-
<%=
|
5
|
+
v<%= @alchemy_version %><br>
|
6
|
+
<small>
|
7
|
+
Ruby v<%= RUBY_VERSION %>, Rails v<%= Rails.version %>
|
8
|
+
</small>
|
4
9
|
</h2>
|
5
10
|
<% if can? :update_check, :alchemy_admin_dashboard %>
|
6
11
|
<p class="center" id="update_check">
|
@@ -17,6 +22,22 @@
|
|
17
22
|
<%= Alchemy.t 'Update status unavailable' %>
|
18
23
|
</span>
|
19
24
|
</p>
|
25
|
+
<script type="text/javascript">
|
26
|
+
var el = $('#update_check');
|
27
|
+
var spinner = new Alchemy.Spinner('small')
|
28
|
+
spinner.spin(el[0])
|
29
|
+
$.get('<%= alchemy.update_check_path %>', function(data, textStatus, jqXHR) {
|
30
|
+
if (data == 'true') {
|
31
|
+
$('#update_available').show()
|
32
|
+
} else {
|
33
|
+
$('#up_to_date').show()
|
34
|
+
}
|
35
|
+
}).fail(function(jqXHR, textStatus, errorThrown) {
|
36
|
+
$('#error').show()
|
37
|
+
}).always(function() {
|
38
|
+
spinner.stop()
|
39
|
+
})
|
40
|
+
</script>
|
20
41
|
<% end %>
|
21
42
|
<%= render_message do %>
|
22
43
|
<p><%= Alchemy.t('Alchemy is open software and itself uses open software and free resources:') %></p>
|
@@ -41,23 +62,3 @@
|
|
41
62
|
</li>
|
42
63
|
</ul>
|
43
64
|
<% end %>
|
44
|
-
<% if can? :update_check, :alchemy_admin_dashboard %>
|
45
|
-
<script type="text/javascript">
|
46
|
-
(function() {
|
47
|
-
var el = $('#update_check');
|
48
|
-
var spinner = new Alchemy.Spinner('small');
|
49
|
-
spinner.spin(el[0]);
|
50
|
-
$.get('<%= alchemy.update_check_path %>', function(data, textStatus, jqXHR) {
|
51
|
-
if (data == 'true') {
|
52
|
-
$('#update_available').show();
|
53
|
-
} else {
|
54
|
-
$('#up_to_date').show();
|
55
|
-
}
|
56
|
-
}).fail(function(jqXHR, textStatus, errorThrown) {
|
57
|
-
$('#error').show();
|
58
|
-
}).always(function() {
|
59
|
-
spinner.stop();
|
60
|
-
});
|
61
|
-
})();
|
62
|
-
</script>
|
63
|
-
<% end %>
|
@@ -13,16 +13,6 @@
|
|
13
13
|
<% end %>
|
14
14
|
</div>
|
15
15
|
<div class="toolbar_spacer"></div>
|
16
|
-
<% unless @page.layoutpage? %>
|
17
|
-
<div class="button_with_label">
|
18
|
-
<%= form_tag alchemy.visit_admin_page_path(@page), id: 'visit_page_form' do %>
|
19
|
-
<button class="icon_button" title="<%= Alchemy.t('Visit page') %>">
|
20
|
-
<%= render_icon('external-link-alt') %>
|
21
|
-
</button>
|
22
|
-
<label><%= Alchemy.t("Visit page") %></label>
|
23
|
-
<% end %>
|
24
|
-
</div>
|
25
|
-
<% end %>
|
26
16
|
<div class="button_with_label">
|
27
17
|
<%= link_to_dialog(
|
28
18
|
render_icon('info-circle'),
|
@@ -76,6 +66,16 @@
|
|
76
66
|
<% end %>
|
77
67
|
</div>
|
78
68
|
<% end %>
|
69
|
+
<% unless @page.layoutpage? %>
|
70
|
+
<div class="button_with_label">
|
71
|
+
<%= form_tag alchemy.visit_admin_page_path(@page), id: 'visit_page_form' do %>
|
72
|
+
<%= button_tag class: 'icon_button', disabled: !@page.public? do %>
|
73
|
+
<%= render_icon('external-link-alt') %>
|
74
|
+
<% end %>
|
75
|
+
<label><%= Alchemy.t("Visit page") %></label>
|
76
|
+
<% end %>
|
77
|
+
</div>
|
78
|
+
<% end %>
|
79
79
|
<% if @page.has_hint? %>
|
80
80
|
<div class="toolbar_spacer"></div>
|
81
81
|
<%= render_hint_for(@page) %>
|
@@ -5,14 +5,6 @@
|
|
5
5
|
label_method: relation[:attr_method],
|
6
6
|
include_blank: Alchemy.t(:blank, scope: 'resources.relation_select'),
|
7
7
|
input_html: {class: 'alchemy_selectbox'} %>
|
8
|
-
<% elsif attribute[:type] == :datetime || attribute[:type] == :time %>
|
9
|
-
<div class="input <%= attribute[:type] %>">
|
10
|
-
<label class="control-label">
|
11
|
-
<%= f.object.class.human_attribute_name(attribute[:name]) %>
|
12
|
-
</label>
|
13
|
-
<%= alchemy_datepicker resource_instance_variable, attribute[:name],
|
14
|
-
type: attribute[:type] %>
|
15
|
-
</div>
|
16
8
|
<% else %>
|
17
9
|
<%= f.input attribute[:name], resource_attribute_field_options(attribute) %>
|
18
10
|
<% end %>
|
@@ -1,5 +1,6 @@
|
|
1
1
|
<div class="resources-header">
|
2
2
|
<h2>
|
3
|
-
<%=
|
3
|
+
<%= resources_instance_variable.total_count %>
|
4
|
+
<%= resource_model.model_name.human(count: resources_instance_variable.total_count) %>
|
4
5
|
</h2>
|
5
6
|
</div>
|
@@ -11,7 +11,7 @@
|
|
11
11
|
<%= content_label(content) %>
|
12
12
|
|
13
13
|
<% if select_values.nil? %>
|
14
|
-
|
14
|
+
<%= warning(':select_values is nil',
|
15
15
|
"<strong>No select values given.</strong>
|
16
16
|
<br>Please provide :<code>select_values</code> either as argument to
|
17
17
|
<code>render_essence_editor</code> helper or as setting on the content definition in
|
@@ -280,7 +280,6 @@ en:
|
|
280
280
|
"User deleted": "%{name} User deleted"
|
281
281
|
"User updated": "%{name} User updated"
|
282
282
|
"Validation failed": "Validation failed"
|
283
|
-
"Version": "Version"
|
284
283
|
"View File": "View File"
|
285
284
|
"Attachment Preview": "Attachment Preview"
|
286
285
|
"Visit page": "Visit page"
|
@@ -612,6 +611,12 @@ en:
|
|
612
611
|
error_notification:
|
613
612
|
default_message: "Please review the problems below:"
|
614
613
|
|
614
|
+
# Alchemy date formats
|
615
|
+
date:
|
616
|
+
formats:
|
617
|
+
alchemy:
|
618
|
+
default: "%Y-%m-%d"
|
619
|
+
|
615
620
|
# Alchemy time formats
|
616
621
|
time:
|
617
622
|
formats:
|
data/lib/alchemy/permissions.rb
CHANGED
@@ -64,8 +64,7 @@ module Alchemy
|
|
64
64
|
|
65
65
|
# Resources
|
66
66
|
can [:show, :download], Alchemy::Attachment
|
67
|
-
can :
|
68
|
-
can :see, Alchemy::Page, restricted: true, visible: true
|
67
|
+
can :see, Alchemy::Page, restricted: true, visible: true
|
69
68
|
|
70
69
|
can :read, Alchemy::Content, Alchemy::Content.available do |c|
|
71
70
|
c.public? && !c.trashed?
|
@@ -74,6 +73,10 @@ module Alchemy
|
|
74
73
|
can :read, Alchemy::Element, Alchemy::Element.available do |e|
|
75
74
|
e.public? && !e.trashed?
|
76
75
|
end
|
76
|
+
|
77
|
+
can :read, Alchemy::Page, Alchemy::Page.published do |p|
|
78
|
+
p.public?
|
79
|
+
end
|
77
80
|
end
|
78
81
|
end
|
79
82
|
|
@@ -78,9 +78,11 @@ module Alchemy
|
|
78
78
|
if attribute[:relation]
|
79
79
|
record = resource.send(attribute[:relation][:name])
|
80
80
|
value = record.present? ? record.send(attribute[:relation][:attr_method]) : Alchemy.t(:not_found)
|
81
|
-
elsif attribute_value &&
|
81
|
+
elsif attribute_value && attribute[:type].to_s =~ /(date|time)/
|
82
82
|
localization_format = if attribute[:type] == :datetime
|
83
83
|
options[:datetime_format] || :'alchemy.default'
|
84
|
+
elsif attribute[:type] == :date
|
85
|
+
options[:date_format] || :'alchemy.default'
|
84
86
|
else
|
85
87
|
options[:time_format] || :'alchemy.time'
|
86
88
|
end
|
@@ -100,19 +102,19 @@ module Alchemy
|
|
100
102
|
# Returns a options hash for simple_form input fields.
|
101
103
|
def resource_attribute_field_options(attribute)
|
102
104
|
options = {hint: resource_handler.help_text_for(attribute)}
|
103
|
-
|
105
|
+
input_type = attribute[:type].to_s
|
106
|
+
case input_type
|
104
107
|
when 'boolean'
|
105
108
|
options
|
106
|
-
when 'date', 'datetime'
|
107
|
-
|
109
|
+
when 'date', 'time', 'datetime'
|
110
|
+
date = resource_instance_variable.send(attribute[:name]) || Time.current
|
111
|
+
options.merge(
|
112
|
+
as: 'string',
|
108
113
|
input_html: {
|
109
|
-
type
|
110
|
-
value:
|
111
|
-
format: "#{attribute[:type]}picker".to_sym
|
112
|
-
)
|
114
|
+
'data-datepicker-type' => input_type,
|
115
|
+
value: date ? date.iso8601 : nil
|
113
116
|
}
|
114
|
-
|
115
|
-
options.merge(as: 'time')
|
117
|
+
)
|
116
118
|
when 'text'
|
117
119
|
options.merge(as: 'text', input_html: {rows: 4})
|
118
120
|
else
|