alchemy_cms 3.3.3 → 3.4.0.rc1

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.
Files changed (133) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -1
  3. data/CHANGELOG.md +42 -4
  4. data/README.md +7 -3
  5. data/alchemy_cms.gemspec +1 -0
  6. data/app/assets/javascripts/alchemy/{alchemy.js → admin.js} +1 -2
  7. data/app/assets/javascripts/alchemy/alchemy.datepicker.js.coffee +28 -25
  8. data/app/assets/javascripts/alchemy/alchemy.dialog.js.coffee +1 -0
  9. data/app/assets/javascripts/alchemy/alchemy.i18n.js.coffee +7 -1
  10. data/app/assets/javascripts/alchemy/alchemy.link_dialog.js.coffee +1 -1
  11. data/app/assets/javascripts/alchemy/alchemy.sitemap.js.coffee +26 -0
  12. data/app/assets/javascripts/alchemy/alchemy.translations.js.coffee +56 -1
  13. data/app/assets/stylesheets/alchemy/_variables.scss +1 -0
  14. data/app/assets/stylesheets/alchemy/admin.scss +2 -1
  15. data/app/assets/stylesheets/alchemy/archive.scss +7 -0
  16. data/app/assets/stylesheets/alchemy/base.scss +0 -42
  17. data/app/assets/stylesheets/alchemy/buttons.scss +2 -1
  18. data/app/assets/stylesheets/alchemy/form_fields.scss +9 -0
  19. data/app/assets/stylesheets/alchemy/forms.scss +36 -10
  20. data/app/assets/stylesheets/alchemy/frame.scss +12 -1
  21. data/app/assets/stylesheets/alchemy/icons.scss +1 -1
  22. data/app/assets/stylesheets/alchemy/jquery-ui.scss +0 -260
  23. data/app/assets/stylesheets/alchemy/jquery.datetimepicker.scss +507 -0
  24. data/app/assets/stylesheets/alchemy/lists.scss +62 -0
  25. data/app/assets/stylesheets/alchemy/selects.scss +9 -2
  26. data/app/assets/stylesheets/alchemy/sitemap.scss +28 -51
  27. data/app/assets/stylesheets/alchemy/toolbar.scss +0 -2
  28. data/app/controllers/alchemy/admin/attachments_controller.rb +4 -6
  29. data/app/controllers/alchemy/admin/base_controller.rb +2 -2
  30. data/app/controllers/alchemy/admin/dashboard_controller.rb +2 -2
  31. data/app/controllers/alchemy/admin/languages_controller.rb +5 -0
  32. data/app/controllers/alchemy/admin/pages_controller.rb +14 -5
  33. data/app/controllers/alchemy/admin/resources_controller.rb +17 -1
  34. data/app/controllers/alchemy/base_controller.rb +1 -0
  35. data/app/controllers/alchemy/messages_controller.rb +1 -1
  36. data/app/controllers/alchemy/pages_controller.rb +16 -26
  37. data/app/controllers/alchemy/pictures_controller.rb +23 -10
  38. data/app/controllers/concerns/alchemy/page_redirects.rb +7 -7
  39. data/app/helpers/alchemy/admin/base_helper.rb +22 -19
  40. data/app/helpers/alchemy/admin/essences_helper.rb +26 -11
  41. data/app/helpers/alchemy/admin/pages_helper.rb +2 -1
  42. data/app/helpers/alchemy/essences_helper.rb +0 -35
  43. data/app/helpers/alchemy/url_helper.rb +1 -1
  44. data/app/mailers/alchemy/base_mailer.rb +18 -0
  45. data/app/mailers/alchemy/{messages.rb → messages_mailer.rb} +1 -1
  46. data/app/models/alchemy/attachment.rb +9 -0
  47. data/app/models/alchemy/cell.rb +1 -1
  48. data/app/models/alchemy/essence_picture.rb +4 -1
  49. data/app/models/alchemy/essence_picture_view.rb +68 -0
  50. data/app/models/alchemy/language.rb +8 -10
  51. data/app/models/alchemy/language/code.rb +4 -1
  52. data/app/models/alchemy/page.rb +69 -26
  53. data/app/models/alchemy/page/page_natures.rb +22 -0
  54. data/app/models/alchemy/page/page_scopes.rb +20 -6
  55. data/app/models/alchemy/picture.rb +37 -4
  56. data/app/models/alchemy/site.rb +8 -0
  57. data/app/serializers/alchemy/page_tree_serializer.rb +1 -1
  58. data/app/views/alchemy/admin/attachments/_archive_overlay.html.erb +9 -6
  59. data/app/views/alchemy/admin/attachments/_file_to_assign.html.erb +11 -9
  60. data/app/views/alchemy/admin/attachments/_filter_bar.html.erb +32 -0
  61. data/app/views/alchemy/admin/attachments/_overlay_file_list.html.erb +14 -2
  62. data/app/views/alchemy/admin/attachments/index.html.erb +10 -9
  63. data/app/views/alchemy/admin/dashboard/_locked_pages.html.erb +20 -9
  64. data/app/views/alchemy/admin/dashboard/_recent_pages.html.erb +11 -1
  65. data/app/views/alchemy/admin/languages/_form.html.erb +1 -0
  66. data/app/views/alchemy/admin/languages/index.html.erb +7 -8
  67. data/app/views/alchemy/admin/layoutpages/_layoutpage.html.erb +1 -1
  68. data/app/views/alchemy/admin/layoutpages/index.html.erb +2 -2
  69. data/app/views/alchemy/admin/pages/_current_page.html.erb +4 -0
  70. data/app/views/alchemy/admin/pages/_form.html.erb +16 -1
  71. data/app/views/alchemy/admin/pages/_locked_page.html.erb +2 -12
  72. data/app/views/alchemy/admin/pages/_page.html.erb +1 -1
  73. data/app/views/alchemy/admin/pages/_page_for_links.html.erb +2 -2
  74. data/app/views/alchemy/admin/pages/_page_status.html.erb +23 -11
  75. data/app/views/alchemy/admin/pages/edit.html.erb +2 -1
  76. data/app/views/alchemy/admin/pages/index.html.erb +2 -2
  77. data/app/views/alchemy/admin/partials/_language_tree_select.html.erb +3 -0
  78. data/app/views/alchemy/admin/partials/_site_select.html.erb +9 -0
  79. data/app/views/alchemy/admin/pictures/_picture.html.erb +6 -1
  80. data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +2 -1
  81. data/app/views/alchemy/admin/pictures/show.html.erb +1 -1
  82. data/app/views/alchemy/admin/resources/_filter_bar.html.erb +31 -0
  83. data/app/views/alchemy/admin/resources/_form.html.erb +6 -0
  84. data/app/views/alchemy/admin/resources/_tag_list.html.erb +16 -0
  85. data/app/views/alchemy/admin/resources/index.html.erb +13 -1
  86. data/app/views/alchemy/essences/_essence_file_view.html.erb +2 -5
  87. data/app/views/alchemy/essences/_essence_picture_view.html.erb +5 -3
  88. data/app/views/alchemy/{messages → messages_mailer}/contact_form_mail.de.text.erb +0 -0
  89. data/app/views/alchemy/{messages → messages_mailer}/contact_form_mail.en.text.erb +0 -0
  90. data/app/views/alchemy/{messages → messages_mailer}/contact_form_mail.es.text.erb +0 -0
  91. data/app/views/alchemy/{messages → messages_mailer}/new.html.erb +0 -0
  92. data/app/views/layouts/alchemy/admin.html.erb +3 -8
  93. data/config/alchemy/config.yml +4 -3
  94. data/config/initializers/assets.rb +2 -2
  95. data/config/initializers/dragonfly.rb +3 -0
  96. data/config/initializers/mime_types.rb +1 -0
  97. data/config/locales/alchemy.de.yml +10 -2
  98. data/config/locales/alchemy.en.yml +6 -2
  99. data/config/locales/alchemy.es.yml +6 -3
  100. data/config/locales/alchemy.fr.yml +6 -2
  101. data/config/locales/alchemy.it.yml +937 -0
  102. data/config/locales/alchemy.nl.yml +6 -2
  103. data/config/locales/alchemy.ru.yml +3 -2
  104. data/config/locales/simple_form.it.yml +25 -0
  105. data/db/migrate/20160108174834_add_timebased_publishing_columns_to_pages.rb +32 -0
  106. data/db/migrate/20160422195310_add_image_file_format_to_alchemy_pictures.rb +21 -0
  107. data/db/migrate/20160617224938_change_alchemy_pages_locked_to_locked_at.rb +22 -0
  108. data/lib/alchemy/ability_helper.rb +23 -0
  109. data/lib/alchemy/configuration_methods.rb +2 -2
  110. data/lib/alchemy/controller_actions.rb +4 -33
  111. data/lib/alchemy/engine.rb +1 -0
  112. data/lib/alchemy/resource.rb +30 -13
  113. data/lib/alchemy/resources_helper.rb +17 -0
  114. data/lib/alchemy/test_support/factories/page_factory.rb +7 -2
  115. data/lib/alchemy/upgrader.rb +1 -0
  116. data/lib/alchemy/upgrader/tasks/install_asset_manifests.rb +15 -0
  117. data/lib/alchemy/upgrader/three_point_four.rb +16 -0
  118. data/lib/alchemy/version.rb +1 -1
  119. data/lib/rails/generators/alchemy/elements/elements_generator.rb +8 -7
  120. data/lib/rails/generators/alchemy/essence/essence_generator.rb +2 -6
  121. data/lib/rails/generators/alchemy/install/files/all.css +11 -0
  122. data/lib/rails/generators/alchemy/install/files/all.js +11 -0
  123. data/lib/rails/generators/alchemy/install/files/{alchemy.elements.css.scss → article.scss} +0 -0
  124. data/lib/rails/generators/alchemy/install/install_generator.rb +20 -19
  125. data/lib/rails/generators/alchemy/module/module_generator.rb +3 -5
  126. data/lib/rails/generators/alchemy/page_layouts/page_layouts_generator.rb +7 -6
  127. data/lib/rails/generators/alchemy/site_layouts/site_layouts_generator.rb +7 -6
  128. data/vendor/assets/javascripts/date-formatter.js +161 -0
  129. data/vendor/assets/javascripts/jquery_plugins/jquery.datetimepicker.full.min.js +2 -0
  130. data/vendor/assets/javascripts/tinymce/langs/it.js +219 -0
  131. metadata +48 -13
  132. data/app/assets/javascripts/alchemy/alchemy.custom.js +0 -1
  133. data/app/assets/stylesheets/alchemy/custom.scss +0 -1
@@ -107,8 +107,11 @@ nl:
107
107
  translations:
108
108
  de: 'DE'
109
109
  en: 'EN'
110
- nl: 'NL'
110
+ es: 'ES'
111
+ it: 'IT'
111
112
  fr: 'FR'
113
+ nl: 'NL'
114
+ ru: 'RU'
112
115
 
113
116
  # == User roles translations
114
117
  user_roles:
@@ -162,7 +165,6 @@ nl:
162
165
  locked_pages: "Actieve pagina's"
163
166
  "Add global page": "Nieuwe globale pagina"
164
167
  "Add page link": "Voeg pagina link toe"
165
- "Adobe Website": "Adobe Website"
166
168
  "Alchemy is open software and itself uses open software and free resources:": "Alchemy is open software en maakt zelf ook gebruik van open software en gratis bronnen"
167
169
  "Alchemy is up to date": "Alchemy is up to date"
168
170
  "An error happened": "Er is een fout opgetreden!"
@@ -609,6 +611,8 @@ nl:
609
611
  page_status: "%m.%d.%Y %H:%M"
610
612
  date: "%Y-%m-%d"
611
613
  datepicker: "%Y-%m-%d"
614
+ timepicker: "%H:%M"
615
+ datetimepicker: "%Y-%m-%d %H:%M"
612
616
  time: "%H:%M"
613
617
  am: "am"
614
618
  pm: "pm"
@@ -107,8 +107,10 @@ ru:
107
107
  translations:
108
108
  de: 'DE'
109
109
  en: 'EN'
110
- nl: 'NL'
110
+ es: 'ES'
111
+ it: 'IT'
111
112
  fr: 'FR'
113
+ nl: 'NL'
112
114
  ru: 'RU'
113
115
 
114
116
  # == User roles translations
@@ -163,7 +165,6 @@ ru:
163
165
  locked_pages: "Активные страницы"
164
166
  "Add global page": "Добавить часть макета"
165
167
  "Add page link": "Добавить ссылку на страницу"
166
- "Adobe Website": "Adobe Website"
167
168
  "Alchemy is open software and itself uses open software and free resources:": "Alchemy is open software and itself uses open software and free resources:"
168
169
  "Alchemy is up to date": 'Alchemy последней версии'
169
170
  'An error happened': 'Произошла ошибка'
@@ -0,0 +1,25 @@
1
+ it:
2
+ simple_form:
3
+ "yes": 'Sì'
4
+ "no": 'No'
5
+ required:
6
+ text: 'obbligatorio'
7
+ mark: '*'
8
+ # You can uncomment the line below if you need to overwrite the whole required html.
9
+ # When using html, text and mark won't be used.
10
+ # html: '<abbr title="required">*</abbr>'
11
+ error_notification:
12
+ default_message: "Correggi gli errori sottostanti:"
13
+ # Labels and hints examples
14
+ # labels:
15
+ # defaults:
16
+ # password: 'Password'
17
+ # user:
18
+ # new:
19
+ # email: 'E-mail to sign in.'
20
+ # edit:
21
+ # email: 'E-mail.'
22
+ # hints:
23
+ # defaults:
24
+ # username: 'User name to sign in.'
25
+ # password: 'No special characters, please.'
@@ -0,0 +1,32 @@
1
+ class AddTimebasedPublishingColumnsToPages < ActiveRecord::Migration
2
+ def up
3
+ add_column :alchemy_pages, :public_on, :datetime
4
+ add_column :alchemy_pages, :public_until, :datetime
5
+ add_index :alchemy_pages, [:public_on, :public_until]
6
+
7
+ update <<-SQL.strip_heredoc
8
+ UPDATE alchemy_pages
9
+ SET public_on = published_at
10
+ WHERE published_at IS NOT NULL AND public=#{ActiveRecord::Base.connection.quoted_true}
11
+ SQL
12
+
13
+ remove_column :alchemy_pages, :public
14
+ end
15
+
16
+ def down
17
+ add_column :alchemy_pages, :public, :boolean, default: false
18
+ current_time = ActiveRecord::Base.connection.quoted_date(Time.current)
19
+
20
+ update <<-SQL.strip_heredoc
21
+ UPDATE alchemy_pages
22
+ SET public = (
23
+ public_on IS NOT NULL AND public_on < '#{current_time}'
24
+ AND (public_until > '#{current_time}' OR public_until IS NULL)
25
+ )
26
+ SQL
27
+
28
+ remove_index :alchemy_pages, [:public_on, :public_until]
29
+ remove_column :alchemy_pages, :public_on
30
+ remove_column :alchemy_pages, :public_until
31
+ end
32
+ end
@@ -0,0 +1,21 @@
1
+ class AddImageFileFormatToAlchemyPictures < ActiveRecord::Migration
2
+ def up
3
+ add_column :alchemy_pictures, :image_file_format, :string
4
+
5
+ say_with_time "Storing file format of existing pictures" do
6
+ Alchemy::Picture.all.each do |pic|
7
+ begin
8
+ format = pic.image_file.identify('-ping -format "%m"')
9
+ pic.update_column('image_file_format', format.to_s.downcase)
10
+ rescue Dragonfly::Job::Fetch::NotFound => e
11
+ say(e.message, true)
12
+ end
13
+ end
14
+ Alchemy::Picture.count
15
+ end
16
+ end
17
+
18
+ def down
19
+ remove_column :alchemy_pictures, :image_file_format
20
+ end
21
+ end
@@ -0,0 +1,22 @@
1
+ class ChangeAlchemyPagesLockedToLockedAt < ActiveRecord::Migration
2
+ def up
3
+ add_column :alchemy_pages, :locked_at, :datetime
4
+ update <<-SQL.strip_heredoc
5
+ UPDATE alchemy_pages
6
+ SET locked_at = updated_at
7
+ WHERE locked=#{ActiveRecord::Base.connection.quoted_true}
8
+ SQL
9
+ remove_column :alchemy_pages, :locked
10
+ add_index :alchemy_pages, [:locked_at, :locked_by]
11
+ end
12
+
13
+ def down
14
+ add_column :alchemy_pages, :locked, :boolean
15
+ update <<-SQL.strip_heredoc
16
+ UPDATE alchemy_pages
17
+ SET locked=#{ActiveRecord::Base.connection.quoted_true}
18
+ WHERE locked_at IS NOT NULL
19
+ SQL
20
+ remove_column :alchemy_pages, :locked_at
21
+ end
22
+ end
@@ -0,0 +1,23 @@
1
+ module Alchemy::AbilityHelper
2
+ # Ensures usage of Alchemy's permissions class.
3
+ #
4
+ # == Register custom Abilities
5
+ #
6
+ # If your app has a CanCan Ability class with rules you want to be aviable in an Alchemy context
7
+ # you need to register it. Or if you have an engine with it's own CanCan abilities you want to
8
+ # add to Alchemy you must register them first.
9
+ #
10
+ # Alchemy.register_ability MyCustom::Permisson
11
+ #
12
+ def current_ability
13
+ @current_ability ||= begin
14
+ alchemy_permissions = Alchemy::Permissions.new(current_alchemy_user)
15
+ Alchemy.registered_abilities.each do |klass|
16
+ # Ensure to avoid issues with Rails constant lookup.
17
+ klass = "::#{klass}".constantize
18
+ alchemy_permissions.merge(klass.new(current_alchemy_user))
19
+ end
20
+ alchemy_permissions
21
+ end
22
+ end
23
+ end
@@ -14,10 +14,10 @@ module Alchemy
14
14
  Config.get(name)
15
15
  end
16
16
 
17
- # Returns true if more than one language is published.
17
+ # Returns true if more than one language is published on current site.
18
18
  #
19
19
  def multi_language?
20
- Language.published.count > 1
20
+ Language.on_current_site.published.count > 1
21
21
  end
22
22
 
23
23
  # Decides if the locale should be prefixed to urls
@@ -49,32 +49,6 @@ module Alchemy
49
49
  @current_alchemy_site ||= Site.find_for_host(request.host)
50
50
  end
51
51
 
52
- # Ensures usage of Alchemy's permissions class.
53
- #
54
- # Merges existing CanCan abilities from host Rails app with Alchemy's own CanCan abilities.
55
- #
56
- # == Register Abilities
57
- #
58
- # If your app's CanCan ability class is not named +Ability+ you have to register it.
59
- # Or if you have a engine with own CanCan abilities you want to add to Alchemy you must register them first.
60
- #
61
- # Alchemy.register_ability MyCustom::Permisson
62
- #
63
- def current_ability
64
- @current_ability ||= begin
65
- alchemy_permissions = Alchemy::Permissions.new(current_alchemy_user)
66
- Alchemy.registered_abilities.each do |klass|
67
- # Ensure to avoid issues with Rails constant lookup.
68
- klass = "::#{klass}".constantize
69
- alchemy_permissions.merge(klass.new(current_alchemy_user))
70
- end
71
- if host_app_ability_present?
72
- alchemy_permissions.merge(::Ability.new(current_alchemy_user))
73
- end
74
- alchemy_permissions
75
- end
76
- end
77
-
78
52
  # Sets the current site in a cvar so the Language model
79
53
  # can be scoped against it.
80
54
  #
@@ -102,9 +76,11 @@ module Alchemy
102
76
  end
103
77
  end
104
78
 
79
+ # Load language from session if it's present on current site.
80
+ # Otherwise return nil so we can load the default language from current site.
105
81
  def load_alchemy_language_from_session
106
82
  if session[:alchemy_language_id].present?
107
- Language.find_by(id: session[:alchemy_language_id])
83
+ Site.current.languages.find_by(id: session[:alchemy_language_id])
108
84
  end
109
85
  end
110
86
 
@@ -113,6 +89,7 @@ module Alchemy
113
89
  Language.find_by_code(id_or_code)
114
90
  end
115
91
 
92
+ # Load the default language from current site.
116
93
  def load_default_alchemy_language
117
94
  Language.default || raise(DefaultLanguageNotFoundError)
118
95
  end
@@ -127,11 +104,5 @@ module Alchemy
127
104
  Language.current = language
128
105
  end
129
106
  end
130
-
131
- def host_app_ability_present?
132
- Object.const_get('::Ability')
133
- rescue
134
- false
135
- end
136
107
  end
137
108
  end
@@ -23,6 +23,7 @@ require 'turbolinks'
23
23
  require 'userstamp'
24
24
 
25
25
  # Require globally used Alchemy mixins
26
+ require_relative './ability_helper'
26
27
  require_relative './admin/locale'
27
28
  require_relative './auth_accessors'
28
29
  require_relative './cache_digests/template_tracker'
@@ -44,6 +44,17 @@ module Alchemy
44
44
  # %w(synced_at remote_record_id)
45
45
  # end
46
46
  #
47
+ # == Searchable attributes
48
+ #
49
+ # By default all :text and :string based attributes are searchable in the admin interface.
50
+ # You can overwrite this behaviour by providing a set of attribute names that should be searchable instead.
51
+ #
52
+ # === Example
53
+ #
54
+ # def self.searchable_alchemy_resource_attributes
55
+ # %w(remote_record_id firstname lastname age)
56
+ # end
57
+ #
47
58
  # == Resource relations
48
59
  #
49
60
  # Alchemy::Resource can take care of ActiveRecord relations.
@@ -90,6 +101,7 @@ module Alchemy
90
101
 
91
102
  DEFAULT_SKIPPED_ATTRIBUTES = %w(id updated_at created_at creator_id updater_id)
92
103
  DEFAULT_SKIPPED_ASSOCIATIONS = %w(creator updater)
104
+ SEARCHABLE_COLUMN_TYPES = [:string, :text]
93
105
 
94
106
  def initialize(controller_path, module_definition = nil, custom_model = nil)
95
107
  @controller_path = controller_path
@@ -158,20 +170,24 @@ module Alchemy
158
170
  attributes.reject { |h| restricted_attributes.map(&:to_s).include?(h[:name].to_s) }
159
171
  end
160
172
 
161
- # Returns all columns that are searchable
162
- #
163
- # For now it only uses string type columns
173
+ # Returns all attribute names that are searchable in the admin interface
164
174
  #
165
- def searchable_attributes
166
- attributes.select { |a| string_attribute?(a) } + searchable_relation_attributes?(attributes)
175
+ def searchable_attribute_names
176
+ if model.respond_to?(:searchable_alchemy_resource_attributes)
177
+ model.searchable_alchemy_resource_attributes
178
+ else
179
+ attributes.select { |a| searchable_attribute?(a) }
180
+ .concat(searchable_relation_attributes(attributes))
181
+ .collect { |h| h[:name] }
182
+ end
167
183
  end
168
184
 
169
185
  # Search field input name
170
186
  #
171
- # Joins all searchable attributes into a Ransack compatible search query
187
+ # Joins all searchable attribute names into a Ransack compatible search query
172
188
  #
173
189
  def search_field_name
174
- searchable_attributes.collect { |a| a[:name] }.join("_or_") + "_cont"
190
+ searchable_attribute_names.join("_or_") + "_cont"
175
191
  end
176
192
 
177
193
  def in_engine?
@@ -220,16 +236,17 @@ module Alchemy
220
236
 
221
237
  private
222
238
 
223
- def string_attribute?(a)
224
- a[:type].to_sym == :string && !a.key?(:relation)
239
+ def searchable_attribute?(a)
240
+ SEARCHABLE_COLUMN_TYPES.include?(a[:type].to_sym) && !a.key?(:relation)
225
241
  end
226
242
 
227
- def string_attribute_on_relation?(a)
228
- a.key?(:relation) && a[:relation][:attr_type].to_sym == :string
243
+ def searchable_attribute_on_relation?(a)
244
+ a.key?(:relation) &&
245
+ SEARCHABLE_COLUMN_TYPES.include?(a[:relation][:attr_type].to_sym)
229
246
  end
230
247
 
231
- def searchable_relation_attributes?(attrs)
232
- attrs.select { |a| string_attribute_on_relation?(a) }.map { |a| searchable_relation_attribute(a) }
248
+ def searchable_relation_attributes(attrs)
249
+ attrs.select { |a| searchable_attribute_on_relation?(a) }.map { |a| searchable_relation_attribute(a) }
233
250
  end
234
251
 
235
252
  def searchable_relation_attribute(a)
@@ -168,5 +168,22 @@ module Alchemy
168
168
  page: params[:page]
169
169
  }
170
170
  end
171
+
172
+ def resource_has_tags
173
+ resource_model.respond_to?(:tag_counts) && resource_model.tag_counts.any?
174
+ end
175
+
176
+ def resource_has_filters
177
+ resource_model.respond_to?(:alchemy_resource_filters)
178
+ end
179
+
180
+ def resource_filter_select
181
+ resource_model.alchemy_resource_filters.map do |filter_scope|
182
+ [
183
+ Alchemy.t(filter_scope.to_sym, scope: ['resources', resource_name, 'filters']),
184
+ filter_scope
185
+ ]
186
+ end
187
+ end
171
188
  end
172
189
  end
@@ -20,13 +20,13 @@ FactoryGirl.define do
20
20
  name 'Startseite'
21
21
  page_layout { language.page_layout }
22
22
  language_root true
23
- public true
23
+ public_on { Time.current }
24
24
  parent_id { Alchemy::Page.root.id }
25
25
  end
26
26
 
27
27
  trait :public do
28
28
  sequence(:name) { |n| "A Public Page #{n}" }
29
- public true
29
+ public_on { Time.current }
30
30
  end
31
31
 
32
32
  trait :system do
@@ -47,5 +47,10 @@ FactoryGirl.define do
47
47
  name "Restricted page"
48
48
  restricted true
49
49
  end
50
+
51
+ trait :locked do
52
+ locked_at { Time.current }
53
+ locked_by { SecureRandom.random_number(1_000_000_000) }
54
+ end
50
55
  end
51
56
  end
@@ -4,6 +4,7 @@ module Alchemy
4
4
  class Upgrader < Alchemy::Seeder
5
5
  Dir["#{File.dirname(__FILE__)}/upgrader/*.rb"].each { |f| require f }
6
6
 
7
+ extend Alchemy::Upgrader::ThreePointFour
7
8
  extend Alchemy::Upgrader::ThreePointThree
8
9
  extend Alchemy::Upgrader::ThreePointTwo
9
10
  extend Alchemy::Upgrader::ThreePointOne
@@ -0,0 +1,15 @@
1
+ module Alchemy::Upgrader::Tasks
2
+ class InstallAssetManifests < Thor
3
+ include Thor::Actions
4
+
5
+ source_root File.expand_path('../../../rails/generators/alchemy/install/files',
6
+ File.dirname(__FILE__))
7
+
8
+ no_tasks do
9
+ def install
10
+ copy_file "all.js", "vendor/assets/javascripts/alchemy/admin/all.js"
11
+ copy_file "all.css", "vendor/assets/stylesheets/alchemy/admin/all.css"
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ require_relative 'tasks/install_asset_manifests'
2
+
3
+ module Alchemy
4
+ module Upgrader::ThreePointFour
5
+ private
6
+
7
+ def install_asset_manifests
8
+ desc 'Install asset manifests into `vendor/assets`'
9
+ Alchemy::Upgrader::Tasks::InstallAssetManifests.new.install
10
+ end
11
+
12
+ def alchemy_3_4_todos
13
+ todo "Nothing todo for Alchemy 3.4 |o/", 'Alchemy v3.4 changes'
14
+ end
15
+ end
16
+ end
@@ -1,5 +1,5 @@
1
1
  module Alchemy
2
- VERSION = "3.3.3"
2
+ VERSION = "3.4.0.rc1"
3
3
 
4
4
  def self.version
5
5
  VERSION