alchemy_cms 5.1.0.beta2 → 5.1.3

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.

Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +126 -0
  3. data/CHANGELOG.md +29 -1
  4. data/Gemfile +1 -1
  5. data/README.md +1 -1
  6. data/alchemy_cms.gemspec +1 -1
  7. data/app/assets/javascripts/alchemy/admin.js +0 -1
  8. data/app/assets/stylesheets/alchemy/_variables.scss +5 -0
  9. data/app/assets/stylesheets/alchemy/admin.scss +0 -1
  10. data/app/assets/stylesheets/alchemy/buttons.scss +26 -15
  11. data/app/assets/stylesheets/alchemy/elements.scss +58 -19
  12. data/app/assets/stylesheets/alchemy/frame.scss +0 -1
  13. data/app/assets/stylesheets/alchemy/hints.scss +2 -1
  14. data/app/assets/stylesheets/alchemy/search.scss +1 -1
  15. data/app/assets/stylesheets/alchemy/selects.scss +23 -19
  16. data/app/assets/stylesheets/alchemy/tables.scss +38 -9
  17. data/app/controllers/alchemy/admin/pages_controller.rb +48 -7
  18. data/app/decorators/alchemy/element_editor.rb +67 -0
  19. data/app/models/alchemy/legacy_page_url.rb +1 -1
  20. data/app/models/alchemy/page.rb +8 -0
  21. data/app/models/alchemy/site/layout.rb +30 -2
  22. data/app/serializers/alchemy/page_tree_serializer.rb +4 -4
  23. data/app/views/alchemy/admin/elements/_element.html.erb +1 -1
  24. data/app/views/alchemy/admin/elements/_element_toolbar.html.erb +1 -1
  25. data/app/views/alchemy/admin/elements/publish.js.erb +1 -0
  26. data/app/views/alchemy/admin/pages/_create_language_form.html.erb +19 -29
  27. data/app/views/alchemy/admin/pages/_new_page_form.html.erb +10 -1
  28. data/app/views/alchemy/admin/pages/_page_layout_filter.html.erb +29 -0
  29. data/app/views/alchemy/admin/pages/_table.html.erb +27 -0
  30. data/app/views/alchemy/admin/pages/_table_row.html.erb +107 -0
  31. data/app/views/alchemy/admin/pages/_toolbar.html.erb +77 -0
  32. data/app/views/alchemy/admin/pages/index.html.erb +41 -74
  33. data/app/views/alchemy/admin/pages/list/_table.html.erb +31 -0
  34. data/app/views/alchemy/admin/pages/unlock.js.erb +2 -2
  35. data/app/views/alchemy/admin/pages/update.js.erb +19 -10
  36. data/app/views/alchemy/admin/resources/_filter_bar.html.erb +13 -11
  37. data/config/locales/alchemy.en.yml +4 -4
  38. data/lib/alchemy/permissions.rb +1 -0
  39. data/lib/alchemy/resource.rb +5 -3
  40. data/lib/alchemy/test_support/integration_helpers.rb +0 -7
  41. data/lib/alchemy/version.rb +1 -1
  42. data/lib/alchemy_cms.rb +0 -1
  43. data/vendor/assets/javascripts/jquery_plugins/select2.js +3729 -0
  44. data/vendor/assets/stylesheets/alchemy_admin/select2.scss +740 -0
  45. metadata +29 -29
  46. data/.travis.yml +0 -48
@@ -74,7 +74,6 @@ div#overlay_text_box {
74
74
 
75
75
  .page_name {
76
76
  display: inline-block;
77
- max-width: 100px;
78
77
  margin-right: $default-margin;
79
78
  line-height: $header-height;
80
79
  white-space: nowrap;
@@ -27,7 +27,8 @@
27
27
 
28
28
  > .hint-bubble {
29
29
  visibility: hidden;
30
- background: $light_yellow;
30
+ background-color: $hint-background-color;
31
+ color: $hint-text-color;
31
32
  border-radius: $default-border-radius;
32
33
  box-shadow: 0px 4px 8px rgba(0, 0, 0, .3);
33
34
  position: absolute;
@@ -54,7 +54,7 @@
54
54
 
55
55
  .search_input_field {
56
56
  width: 0;
57
- height: inherit;
57
+ height: 100%;
58
58
  border: none;
59
59
  background-color: transparentize($form-field-background-color, 0.25);
60
60
  transition:
@@ -1,13 +1,16 @@
1
+ @import "alchemy_admin/select2";
2
+
1
3
  select {
2
4
  @include button-defaults(
3
5
  $background-color: $form-field-background-color,
4
6
  $hover-color: $form-field-background-color,
5
7
  $hover-border-color: darken($default-border-color, 10%),
6
- $padding: 0 2*$default-padding,
8
+ $padding: 0 2 * $default-padding,
7
9
  $border: 1px solid $default-border-color,
8
10
  $box-shadow: none,
9
11
  $color: $text-color,
10
- $margin: 0);
12
+ $margin: 0
13
+ );
11
14
  height: $form-field-height;
12
15
  padding: 0.4em 0.6em;
13
16
  max-width: 100%;
@@ -32,7 +35,8 @@ select {
32
35
  $border: 1px solid $default-border-color,
33
36
  $box-shadow: none,
34
37
  $color: $text-color,
35
- $margin: 0);
38
+ $margin: 0
39
+ );
36
40
  background-image: none;
37
41
  display: block;
38
42
  font-weight: normal;
@@ -79,14 +83,13 @@ select {
79
83
  }
80
84
 
81
85
  &.select2-container-active {
82
-
83
- .select2-choice, .select2-choices {
86
+ .select2-choice,
87
+ .select2-choices {
84
88
  @include default-focus-style($box-shadow: 0 0 0 1px $focus-color);
85
89
  }
86
90
  }
87
91
 
88
92
  &.select2-container-disabled {
89
-
90
93
  &:hover {
91
94
  + .with-hint > .hint-bubble {
92
95
  @include hint-hover-style;
@@ -98,7 +101,8 @@ select {
98
101
  top: 0;
99
102
  }
100
103
 
101
- .select2-choice, .select2-choice:hover {
104
+ .select2-choice,
105
+ .select2-choice:hover {
102
106
  background-image: none;
103
107
  background-color: $light-gray;
104
108
  box-shadow: none;
@@ -108,7 +112,9 @@ select {
108
112
  .select2-arrow {
109
113
  border-color: $border-inset-color;
110
114
 
111
- b { color: $border-inset-color; }
115
+ b {
116
+ color: $border-inset-color;
117
+ }
112
118
  }
113
119
  }
114
120
  }
@@ -142,7 +148,6 @@ select {
142
148
  margin-top: 0 !important;
143
149
 
144
150
  &.select2-container-active {
145
-
146
151
  .select2-choices {
147
152
  @include default-focus-style($box-shadow: 0 0 0 1px $focus-color);
148
153
  }
@@ -214,7 +219,8 @@ select {
214
219
  }
215
220
  }
216
221
 
217
- .select2-no-results, .select2-searching {
222
+ .select2-no-results,
223
+ .select2-searching {
218
224
  padding: 8px;
219
225
  margin: 0;
220
226
  }
@@ -235,41 +241,39 @@ select {
235
241
 
236
242
  .select2-more-results,
237
243
  .select2-ajax-error {
238
- padding: 2*$default-padding;
244
+ padding: 2 * $default-padding;
239
245
  margin-bottom: 0;
240
246
  }
241
247
  }
242
248
 
243
- .window_form, #filter_bar {
244
-
249
+ .window_form,
250
+ #filter_bar {
245
251
  .select2-container {
246
252
  width: 100%;
247
253
  }
248
254
  }
249
255
 
250
256
  .select_with_label {
251
- margin: 0 3*$default-margin;
257
+ margin: 0 3 * $default-margin;
252
258
  display: inline-block;
253
259
  vertical-align: middle;
254
260
 
255
261
  label {
256
262
  display: inline-block;
257
263
  vertical-align: middle;
258
- margin-right: 2*$default-margin;
264
+ margin-right: 2 * $default-margin;
259
265
  }
260
266
  }
261
267
 
262
268
  // overriding important of select2 default style for retina screens
263
269
  @media only screen and (-webkit-min-device-pixel-ratio: 1.5),
264
- only screen and (min-resolution: 2dppx) {
265
-
270
+ only screen and (min-resolution: 2dppx) {
266
271
  #alchemy {
267
-
268
272
  .select2-search input,
269
273
  .select2-search-choice-close,
270
274
  .select2-container .select2-choice abbr,
271
275
  .select2-container .select2-choice .select2-arrow b {
272
- background-image: none !important;
276
+ background-image: none !important;
273
277
  }
274
278
  }
275
279
  }
@@ -6,7 +6,8 @@ table {
6
6
  width: 100%;
7
7
 
8
8
  &.list .tools {
9
- button, a {
9
+ button,
10
+ a {
10
11
  display: inline-block;
11
12
  width: 18px;
12
13
  height: 18px;
@@ -22,8 +23,9 @@ table {
22
23
  }
23
24
  }
24
25
 
25
- .list td, .list th {
26
- padding: 2*$default-padding;
26
+ .list td,
27
+ .list th {
28
+ padding: 2 * $default-padding;
27
29
  vertical-align: top;
28
30
  line-height: 18px;
29
31
  border-right: 1px solid $medium-gray;
@@ -93,9 +95,10 @@ td.heading {
93
95
  background-color: $table-row-hover-color;
94
96
  }
95
97
 
96
- td, th {
97
-
98
- &.center, &.boolean {
98
+ td,
99
+ th {
100
+ &.center,
101
+ &.boolean {
99
102
  text-align: center;
100
103
  }
101
104
 
@@ -105,7 +108,6 @@ td, th {
105
108
  }
106
109
 
107
110
  td {
108
-
109
111
  &.file_name {
110
112
  word-break: break-all;
111
113
  }
@@ -118,7 +120,8 @@ td {
118
120
  width: 80px;
119
121
  }
120
122
 
121
- &.date, &.datetime {
123
+ &.date,
124
+ &.datetime {
122
125
  width: 150px;
123
126
  }
124
127
 
@@ -137,9 +140,35 @@ td {
137
140
  &.rights {
138
141
  width: 60px;
139
142
  }
143
+
144
+ &.page_layout {
145
+ width: 160px;
146
+ }
147
+
148
+ &.status {
149
+ width: 80px;
150
+
151
+ .page_status {
152
+ margin: 0 $default-margin;
153
+ }
154
+ }
155
+
156
+ &.tags {
157
+ width: 180px;
158
+
159
+ .tag {
160
+ margin: 0;
161
+ padding: 0 2 + $default-padding;
162
+
163
+ &:before {
164
+ padding-right: $default-padding;
165
+ }
166
+ }
167
+ }
140
168
  }
141
169
 
142
- th.count, td.count {
170
+ th.count,
171
+ td.count {
143
172
  width: 120px;
144
173
  text-align: right;
145
174
  padding-right: 16px;
@@ -2,12 +2,12 @@
2
2
 
3
3
  module Alchemy
4
4
  module Admin
5
- class PagesController < Alchemy::Admin::BaseController
5
+ class PagesController < ResourcesController
6
6
  include OnPageLayout::CallbacksRunner
7
7
 
8
8
  helper "alchemy/pages"
9
9
 
10
- before_action :load_page, except: [:index, :flush, :new, :order, :create, :copy_language_tree, :link, :sort]
10
+ before_action :load_resource, except: [:index, :flush, :new, :order, :create, :copy_language_tree, :link, :sort]
11
11
 
12
12
  authorize_resource class: Alchemy::Page, except: [:index, :tree]
13
13
 
@@ -27,11 +27,33 @@ module Alchemy
27
27
  if: :run_on_page_layout_callbacks?,
28
28
  only: [:show]
29
29
 
30
+ before_action :load_languages_and_layouts,
31
+ unless: -> { @page_root },
32
+ only: [:index]
33
+
34
+ before_action :set_view, only: [:index]
35
+
30
36
  def index
31
- if !@page_root
32
- @language = @current_language
33
- @languages_with_page_tree = Language.on_current_site.with_root_page
34
- @page_layouts = PageLayout.layouts_for_select(@language.id)
37
+ @query = @current_language.pages.contentpages.ransack(search_filter_params[:q])
38
+
39
+ if @view == "list"
40
+ @query.sorts = default_sort_order if @query.sorts.empty?
41
+ items = @query.result
42
+
43
+ if search_filter_params[:tagged_with].present?
44
+ items = items.tagged_with(search_filter_params[:tagged_with])
45
+ end
46
+
47
+ if search_filter_params[:filter].present?
48
+ items = items.public_send(sanitized_filter_params)
49
+ end
50
+
51
+ if search_filter_params[:page_layout].present?
52
+ items = items.where(page_layout: search_filter_params[:page_layout])
53
+ end
54
+
55
+ items = items.page(params[:page] || 1).per(items_per_page)
56
+ @pages = items
35
57
  end
36
58
  end
37
59
 
@@ -229,6 +251,19 @@ module Alchemy
229
251
 
230
252
  private
231
253
 
254
+ def resource_handler
255
+ @_resource_handler ||= Alchemy::Resource.new(controller_path, alchemy_module, Alchemy::Page)
256
+ end
257
+
258
+ def common_search_filter_includes
259
+ super.push(:page_layout, :view)
260
+ end
261
+
262
+ def set_view
263
+ @view = params[:view] || session[:alchemy_pages_view] || "tree"
264
+ session[:alchemy_pages_view] = @view
265
+ end
266
+
232
267
  def copy_of_language_root
233
268
  Page.copy(
234
269
  language_root_to_copy_from,
@@ -310,7 +345,7 @@ module Alchemy
310
345
  { my_urlname: default_urlname, children_path: default_urlname }
311
346
  end
312
347
 
313
- def load_page
348
+ def load_resource
314
349
  @page = Page.find(params[:id])
315
350
  end
316
351
 
@@ -373,6 +408,12 @@ module Alchemy
373
408
  user: current_alchemy_user,
374
409
  full: params[:full] == "true")
375
410
  end
411
+
412
+ def load_languages_and_layouts
413
+ @language = @current_language
414
+ @languages_with_page_tree = Language.on_current_site.with_root_page
415
+ @page_layouts = PageLayout.layouts_for_select(@language.id)
416
+ end
376
417
  end
377
418
  end
378
419
  end
@@ -8,6 +8,17 @@ module Alchemy
8
8
  "alchemy/admin/elements/element"
9
9
  end
10
10
 
11
+ # Returns content editor instances for defined contents
12
+ #
13
+ # Creates contents on demand if the content is not yet present on the element
14
+ #
15
+ # @return Array<Alchemy::ContentEditor>
16
+ def contents
17
+ element.definition.fetch(:contents, []).map do |content|
18
+ Alchemy::ContentEditor.new(find_or_create_content(content[:name]))
19
+ end
20
+ end
21
+
11
22
  # CSS classes for the element editor partial.
12
23
  def css_classes
13
24
  [
@@ -18,6 +29,7 @@ module Alchemy
18
29
  folded ? "folded" : "expanded",
19
30
  compact? ? "compact" : nil,
20
31
  fixed? ? "is-fixed" : "not-fixed",
32
+ public? ? "visible" : "hidden",
21
33
  ].join(" ")
22
34
  end
23
35
 
@@ -35,5 +47,60 @@ module Alchemy
35
47
 
36
48
  super
37
49
  end
50
+
51
+ # Returns a deprecation notice for elements marked deprecated
52
+ #
53
+ # You can either use localizations or pass a String as notice
54
+ # in the element definition.
55
+ #
56
+ # == Custom deprecation notices
57
+ #
58
+ # Use general element deprecation notice
59
+ #
60
+ # - name: old_element
61
+ # deprecated: true
62
+ #
63
+ # Add a translation to your locale file for a per element notice.
64
+ #
65
+ # en:
66
+ # alchemy:
67
+ # element_deprecation_notices:
68
+ # old_element: Foo baz widget is deprecated
69
+ #
70
+ # or use the global translation that apply to all deprecated elements.
71
+ #
72
+ # en:
73
+ # alchemy:
74
+ # element_deprecation_notice: Foo baz widget is deprecated
75
+ #
76
+ # or pass string as deprecation notice.
77
+ #
78
+ # - name: old_element
79
+ # deprecated: This element will be removed soon.
80
+ #
81
+ def deprecation_notice
82
+ case definition["deprecated"]
83
+ when String
84
+ definition["deprecated"]
85
+ when TrueClass
86
+ Alchemy.t(name,
87
+ scope: :element_deprecation_notices,
88
+ default: Alchemy.t(:element_deprecated))
89
+ end
90
+ end
91
+
92
+ private
93
+
94
+ def find_or_create_content(name)
95
+ find_content(name) || create_content(name)
96
+ end
97
+
98
+ def find_content(name)
99
+ element.contents.find { |content| content.name == name }
100
+ end
101
+
102
+ def create_content(name)
103
+ Alchemy::Content.create(element: element, name: name)
104
+ end
38
105
  end
39
106
  end
@@ -18,5 +18,5 @@ class Alchemy::LegacyPageUrl < ActiveRecord::Base
18
18
 
19
19
  validates :urlname,
20
20
  presence: true,
21
- format: {with: /\A[:\.\w\-+_\/\?&%;=]*\z/}
21
+ format: {with: /\A[:\.\w\-+_\/\?&%;=#]*\z/}
22
22
  end
@@ -164,6 +164,14 @@ module Alchemy
164
164
  @_url_path_class = klass
165
165
  end
166
166
 
167
+ def alchemy_resource_filters
168
+ %w[published not_public restricted]
169
+ end
170
+
171
+ def searchable_alchemy_resource_attributes
172
+ %w[name urlname title]
173
+ end
174
+
167
175
  # Used to store the current page previewed in the edit page template.
168
176
  #
169
177
  def current_preview=(page)