alchemy_cms 3.3.3 → 3.4.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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