locomotive_cms 2.1.4 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (143) hide show
  1. data/Gemfile +1 -5
  2. data/app/assets/images/locomotive/icons/flags/zh-CN.png +0 -0
  3. data/app/assets/javascripts/aloha/plugins/custom/inputcontrol/css/inputcontrol.css +3 -0
  4. data/app/assets/javascripts/aloha/plugins/custom/inputcontrol/lib/inputcontrol-plugin.js +94 -0
  5. data/app/assets/javascripts/aloha/plugins/custom/inputcontrol/package.json +1 -0
  6. data/app/assets/javascripts/locomotive.js +2 -1
  7. data/app/assets/javascripts/locomotive/models/content_type.js.coffee +6 -2
  8. data/app/assets/javascripts/locomotive/models/page.js.coffee +1 -1
  9. data/app/assets/javascripts/locomotive/models/site.js.coffee +1 -1
  10. data/app/assets/javascripts/locomotive/utils/aloha_settings.js.coffee +17 -7
  11. data/app/assets/javascripts/locomotive/utils/tinymce_settings.js.coffee +6 -0
  12. data/app/assets/javascripts/locomotive/views/application_view.js.coffee +13 -2
  13. data/app/assets/javascripts/locomotive/views/content_entries/_form_view.js.coffee +19 -2
  14. data/app/assets/javascripts/locomotive/views/content_entries/_popup_form_view.js.coffee +1 -1
  15. data/app/assets/javascripts/locomotive/views/content_entries/index_view.js.coffee +2 -2
  16. data/app/assets/javascripts/locomotive/views/content_types/_form_view.js.coffee +2 -1
  17. data/app/assets/javascripts/locomotive/views/content_types/custom_field_entry_view.js.coffee +3 -0
  18. data/app/assets/javascripts/locomotive/views/current_site/edit_view.js.coffee +2 -1
  19. data/app/assets/javascripts/locomotive/views/editable_elements/edit_all_view.js.coffee +3 -6
  20. data/app/assets/javascripts/locomotive/views/editable_elements/text_view.js.coffee +47 -0
  21. data/app/assets/javascripts/locomotive/views/inline_editor/toolbar_view.js.coffee +1 -1
  22. data/app/assets/javascripts/locomotive/views/pages/_form_view.js.coffee +2 -1
  23. data/app/assets/javascripts/locomotive/views/pages/list_view.js.coffee +2 -2
  24. data/app/assets/javascripts/locomotive/views/shared/fields/belongs_to_view.js.coffee +32 -0
  25. data/app/assets/javascripts/locomotive/views/shared/fields/has_many_view.js.coffee +2 -2
  26. data/app/assets/javascripts/locomotive/views/shared/fields/many_to_many_view.js.coffee +2 -2
  27. data/app/assets/javascripts/locomotive/views/shared/form_view.js.coffee +2 -0
  28. data/app/assets/javascripts/locomotive/views/snippets/_form_view.js.coffee +2 -1
  29. data/app/assets/javascripts/locomotive/views/theme_assets/_form_view.js.coffee +2 -1
  30. data/app/assets/javascripts/locomotive/views/theme_assets/index_view.js.coffee +0 -1
  31. data/app/assets/javascripts/tinymce/plugins/locomotive_media/langs/es.js +1 -0
  32. data/app/assets/javascripts/tinymce/plugins/locomotive_media/langs/et.js +1 -0
  33. data/app/assets/javascripts/tinymce/plugins/locomotive_media/langs/it.js +1 -0
  34. data/app/assets/javascripts/tinymce/plugins/locomotive_media/langs/ja.js +1 -0
  35. data/app/assets/javascripts/tinymce/plugins/locomotive_media/langs/nb.js +1 -0
  36. data/app/assets/javascripts/tinymce/plugins/locomotive_media/langs/nl.js +1 -0
  37. data/app/assets/javascripts/tinymce/plugins/locomotive_media/langs/no.js +1 -0
  38. data/app/assets/javascripts/tinymce/plugins/locomotive_media/langs/pl.js +1 -0
  39. data/app/assets/javascripts/tinymce/plugins/locomotive_media/langs/pt.js +1 -0
  40. data/app/assets/javascripts/tinymce/plugins/locomotive_media/langs/zh-cn.js +1 -0
  41. data/app/assets/stylesheets/locomotive.css +1 -0
  42. data/app/assets/stylesheets/locomotive/backoffice/codemirror_changes.css.scss +2 -0
  43. data/app/assets/stylesheets/locomotive/backoffice/formtastic_changes.css.scss +17 -3
  44. data/app/controllers/locomotive/content_entries_controller.rb +6 -2
  45. data/app/controllers/locomotive/public/content_entries_controller.rb +6 -0
  46. data/app/helpers/locomotive/base_helper.rb +8 -0
  47. data/app/helpers/locomotive/sites_helper.rb +6 -0
  48. data/app/models/locomotive/content_entry.rb +35 -5
  49. data/app/models/locomotive/content_type.rb +26 -8
  50. data/app/models/locomotive/editable_element.rb +15 -1
  51. data/app/models/locomotive/editable_file.rb +0 -2
  52. data/app/models/locomotive/editable_long_text.rb +3 -3
  53. data/app/models/locomotive/editable_short_text.rb +3 -64
  54. data/app/models/locomotive/editable_text.rb +84 -0
  55. data/app/models/locomotive/extensions/content_entry/csv.rb +7 -3
  56. data/app/models/locomotive/extensions/page/editable_elements.rb +3 -5
  57. data/app/models/locomotive/extensions/site/locales.rb +20 -0
  58. data/app/models/locomotive/extensions/site/timezone.rb +35 -0
  59. data/app/models/locomotive/site.rb +20 -16
  60. data/app/models/locomotive/theme_asset.rb +1 -1
  61. data/app/presenters/locomotive/content_entry_presenter.rb +1 -1
  62. data/app/presenters/locomotive/{editable_short_text_presenter.rb → editable_text_presenter.rb} +14 -2
  63. data/app/views/locomotive/current_site/_form.html.haml +1 -0
  64. data/app/views/locomotive/custom_fields/types/_belongs_to.html.haml +6 -5
  65. data/app/views/locomotive/pages/_editable_elements.html.haml +1 -1
  66. data/app/views/locomotive/shared/_head.html.haml +2 -0
  67. data/app/views/locomotive/shared/_main_app_head_before_backbone.html.haml +1 -0
  68. data/config/locales/admin_ui.de.yml +1 -0
  69. data/config/locales/admin_ui.en.yml +1 -0
  70. data/config/locales/admin_ui.et.yml +1 -0
  71. data/config/locales/admin_ui.fr.yml +1 -0
  72. data/config/locales/admin_ui.ja.yml +1 -0
  73. data/config/locales/admin_ui.nb.yml +2 -0
  74. data/config/locales/admin_ui.pl.yml +1 -0
  75. data/config/locales/admin_ui.pt-BR.yml +2 -1
  76. data/config/locales/admin_ui.ru.yml +24 -4
  77. data/config/locales/admin_ui.zh-CN.yml +347 -0
  78. data/config/locales/carrierwave.zh-CN.yml +4 -0
  79. data/config/locales/default.zh-CN.yml +116 -0
  80. data/config/locales/devise.nb.yml +1 -0
  81. data/config/locales/devise.zh-CN.yml +64 -0
  82. data/config/locales/flash.zh-CN.yml +115 -0
  83. data/config/locales/formtastic.en.yml +1 -0
  84. data/config/locales/formtastic.ru.yml +4 -1
  85. data/config/locales/formtastic.zh-CN.yml +112 -0
  86. data/features/backoffice/content_types/localized.feature +63 -0
  87. data/features/backoffice/pages.feature +3 -1
  88. data/features/backoffice/site.feature +7 -0
  89. data/features/public/contact_form.feature +11 -0
  90. data/features/public/content_entries.feature +13 -0
  91. data/features/public/pages.feature +24 -0
  92. data/features/step_definitions/page_steps.rb +6 -0
  93. data/features/step_definitions/web_steps.rb +24 -7
  94. data/lib/generators/locomotive/install/templates/locomotive.rb +2 -2
  95. data/lib/generators/locomotive/install/templates/mongoid.yml +23 -29
  96. data/lib/locomotive.rb +1 -4
  97. data/lib/locomotive/configuration.rb +3 -3
  98. data/lib/locomotive/dependencies.rb +1 -0
  99. data/lib/locomotive/engine.rb +2 -1
  100. data/lib/locomotive/liquid/drops/page.rb +1 -1
  101. data/lib/locomotive/liquid/filters/date.rb +3 -1
  102. data/lib/locomotive/liquid/filters/misc.rb +4 -0
  103. data/lib/locomotive/liquid/filters/text.rb +4 -0
  104. data/lib/locomotive/liquid/tags/editable.rb +1 -2
  105. data/lib/locomotive/liquid/tags/editable/text.rb +79 -0
  106. data/lib/locomotive/liquid/tags/inline_editor.rb +1 -1
  107. data/lib/locomotive/liquid/tags/link_to.rb +72 -13
  108. data/lib/locomotive/liquid/tags/with_scope.rb +3 -3
  109. data/lib/locomotive/middlewares.rb +0 -1
  110. data/lib/locomotive/mongoid/patches.rb +0 -16
  111. data/lib/locomotive/render.rb +1 -1
  112. data/lib/locomotive/version.rb +1 -1
  113. data/lib/tasks/locomotive.rake +15 -9
  114. data/mongodb/migrate/20130326201349_rename_entry_to_content_entry.rb +1 -1
  115. data/mongodb/migrate/20130621135025_create_editable_texts.rb +42 -0
  116. data/mongodb/migrate/20130627101548_localize_slugs_of_content_entries.rb +43 -0
  117. data/spec/dummy/config/initializers/locomotive.rb +1 -1
  118. data/spec/dummy/config/initializers/session_store.rb +1 -1
  119. data/spec/lib/locomotive/liquid/drops/page_spec.rb +1 -1
  120. data/spec/lib/locomotive/liquid/filters/misc_spec.rb +26 -0
  121. data/spec/lib/locomotive/liquid/tags/editable/text_spec.rb +85 -0
  122. data/spec/lib/locomotive/liquid/tags/link_to_spec.rb +111 -0
  123. data/spec/lib/locomotive/liquid/tags/with_scope_spec.rb +6 -0
  124. data/spec/models/locomotive/content_entry_spec.rb +27 -7
  125. data/spec/models/locomotive/{editable_short_text_spec.rb → editable_text_spec.rb} +53 -8
  126. data/spec/models/locomotive/extensions/page/editable_elements_spec.rb +6 -6
  127. data/spec/models/locomotive/site_spec.rb +52 -32
  128. data/vendor/assets/images/select2-spinner.gif +0 -0
  129. data/vendor/assets/images/select2.png +0 -0
  130. data/vendor/assets/images/select2x2.png +0 -0
  131. data/vendor/assets/javascripts/locomotive/liquid_mode.js +1 -1
  132. data/vendor/assets/javascripts/select2/select2.js +3054 -0
  133. data/vendor/assets/stylesheets/select2/select2.css.scss +652 -0
  134. metadata +77 -33
  135. data/app/assets/javascripts/locomotive/views/editable_elements/long_text_view.js.coffee +0 -36
  136. data/app/assets/javascripts/locomotive/views/editable_elements/short_text_view.js.coffee +0 -22
  137. data/app/presenters/locomotive/editable_long_text_presenter.rb +0 -5
  138. data/lib/locomotive/liquid/tags/editable/long_text.rb +0 -33
  139. data/lib/locomotive/liquid/tags/editable/short_text.rb +0 -41
  140. data/lib/locomotive/middlewares/fonts.rb +0 -42
  141. data/lib/locomotive/session_store.rb +0 -64
  142. data/spec/lib/locomotive/liquid/tags/editable/short_text_spec.rb +0 -46
  143. data/spec/models/locomotive/editable_long_text_spec.rb +0 -50
@@ -34,7 +34,7 @@ class Locomotive.Views.Pages.ListView extends Backbone.View
34
34
  error: @.on_failed_sort
35
35
 
36
36
  on_successful_sort: (data, status, xhr) ->
37
- $.growl('success', xhr.getResponseHeader('X-Message'))
37
+ $.growl('success', decodeURIComponent $.parseJSON xhr.getResponseHeader('X-Message'))
38
38
 
39
39
  on_failed_sort: (data, status, xhr) ->
40
- $.growl('error', xhr.getResponseHeader('X-Message'))
40
+ $.growl('error', decodeURIComponent $.parseJSON xhr.getResponseHeader('X-Message'))
@@ -0,0 +1,32 @@
1
+ Locomotive.Views.Shared ||= {}
2
+ Locomotive.Views.Shared.Fields ||= {}
3
+
4
+ class Locomotive.Views.Shared.Fields.BelongsToView extends Backbone.View
5
+
6
+ render: ->
7
+ @enable_select2()
8
+
9
+ return @
10
+
11
+ enable_select2: ->
12
+ options = $(@el).data()
13
+
14
+ $(@el).select2
15
+ width: '50%'
16
+ minimumInputLength: 1
17
+ quietMillis: 100
18
+ ajax:
19
+ url: options.url
20
+ data: (term, page) ->
21
+ q: term
22
+ page: page
23
+ results: (data, page) ->
24
+ results: data.map (item) -> { id: item._id, text: item._label || '' }
25
+ more: data.length == options.perPage
26
+
27
+ initSelection: (el, callback) -> callback(id: el.val(), text: options.value)
28
+
29
+ $(@el).on 'select2-selecting', (el) =>
30
+ @model.set "#{@options.name}_id", el.val
31
+
32
+
@@ -26,7 +26,7 @@ class Locomotive.Views.Shared.Fields.HasManyView extends Backbone.View
26
26
  @build_target_entry_view()
27
27
 
28
28
  render: ->
29
- $(@el).html(@template()())
29
+ $(@el).html(@template()()).attr('id', "#{@model.paramRoot}_#{@options.name}")
30
30
 
31
31
  @insert_entries()
32
32
 
@@ -101,7 +101,7 @@ class Locomotive.Views.Shared.Fields.HasManyView extends Backbone.View
101
101
  remove_entry: (event) ->
102
102
  event.stopPropagation() & event.preventDefault()
103
103
 
104
- if confirm($(event.target).data('confirm'))
104
+ if confirm($(event.target).closest('a').data('confirm'))
105
105
  entry = @get_entry_from_element($(event.target))
106
106
  entry.set _destroy: true
107
107
 
@@ -25,7 +25,7 @@ class Locomotive.Views.Shared.Fields.ManyToManyView extends Backbone.View
25
25
  @all_entries = @options.all_entries
26
26
 
27
27
  render: ->
28
- $(@el).html(@template()())
28
+ $(@el).html(@template()()).attr('id', "#{@model.paramRoot}_#{@options.name}_ids")
29
29
 
30
30
  @insert_entries()
31
31
 
@@ -80,7 +80,7 @@ class Locomotive.Views.Shared.Fields.ManyToManyView extends Backbone.View
80
80
  remove_entry: (event) ->
81
81
  event.stopPropagation() & event.preventDefault()
82
82
 
83
- if confirm($(event.target).data('confirm'))
83
+ if confirm($(event.target).closest('a').data('confirm'))
84
84
  entry = @get_entry_from_element($(event.target))
85
85
  @collection.remove(entry)
86
86
 
@@ -44,6 +44,7 @@ class Locomotive.Views.Shared.FormView extends Backbone.View
44
44
  xhr.success (model, response, _options) =>
45
45
  form.trigger('ajax:complete')
46
46
 
47
+ @model.set(previous_attributes)
47
48
  model.attributes = previous_attributes
48
49
 
49
50
  options.on_success(model, xhr) if options.on_success
@@ -116,6 +117,7 @@ class Locomotive.Views.Shared.FormView extends Backbone.View
116
117
 
117
118
  input = @$("##{prefix}#{@model.paramRoot}_#{attribute}")
118
119
  input = @$("##{prefix}#{@model.paramRoot}_#{attribute}_id") if input.size() == 0
120
+ input = @$("##{prefix}#{@model.paramRoot}_#{attribute}_ids") if input.size() == 0
119
121
 
120
122
  return unless input.size() > 0
121
123
 
@@ -72,7 +72,8 @@ class Locomotive.Views.Snippets.FormView extends Locomotive.Views.Shared.FormVie
72
72
  passDelay: 50
73
73
  tabMode: 'shift'
74
74
  theme: 'default medium'
75
- onChange: (editor) => @model.set(template: editor.getValue())
75
+
76
+ @editor.on 'change', (editor, change) => @model.set(template: editor.getValue())
76
77
 
77
78
  after_inputs_fold: ->
78
79
  @editor.refresh()
@@ -94,7 +94,8 @@ class Locomotive.Views.ThemeAssets.FormView extends Locomotive.Views.Shared.Form
94
94
  passDelay: 50
95
95
  tabMode: 'shift'
96
96
  theme: 'default'
97
- onChange: (editor) => @model.set(plain_text: editor.getValue())
97
+
98
+ @editor.on 'change', (editor, change) => @model.set(plain_text: editor.getValue())
98
99
 
99
100
  bind_source_mode: ->
100
101
  @$('#theme_asset_plain_text_type').bind 'change', (event) =>
@@ -49,7 +49,6 @@ class Locomotive.Views.ThemeAssets.IndexView extends Backbone.View
49
49
  headers: { 'X-Flash': true }
50
50
 
51
51
  insert_asset: (model) ->
52
- window.foo = model
53
52
  list_view = @pick_list_view(model.get('content_type'))
54
53
  list_view.collection.add(model) if list_view?
55
54
 
@@ -0,0 +1 @@
1
+ tinyMCE.addI18n('es.locomotive_media',{"image_desc": "Inserte los medios de comunicación"});
@@ -0,0 +1 @@
1
+ tinyMCE.addI18n('et.locomotive_media',{"image_desc": "Sisesta meedia"});
@@ -0,0 +1 @@
1
+ tinyMCE.addI18n('it.locomotive_media',{"image_desc": "Inserire un supporto"});
@@ -0,0 +1 @@
1
+ tinyMCE.addI18n('ja.locomotive_media',{"image_desc": "メディアを挿入"});
@@ -0,0 +1 @@
1
+ tinyMCE.addI18n('nb.locomotive_media',{"image_desc": "Sett inn media"});
@@ -0,0 +1 @@
1
+ tinyMCE.addI18n('nl.locomotive_media',{"image_desc": "Steek media"});
@@ -0,0 +1 @@
1
+ tinyMCE.addI18n('no.locomotive_media',{"image_desc": "Sett inn media"});
@@ -0,0 +1 @@
1
+ tinyMCE.addI18n('pl.locomotive_media',{"image_desc": "Włóż nośnik"});
@@ -0,0 +1 @@
1
+ tinyMCE.addI18n('pt.locomotive_media',{"image_desc": "Insira a mídia"});
@@ -0,0 +1 @@
1
+ tinyMCE.addI18n('zh-cn.locomotive_media',{"image_desc": "插入媒体"});
@@ -8,6 +8,7 @@
8
8
  *= require locomotive/jquery.tagit.css
9
9
  *= require locomotive/font-awesome
10
10
  *= require formtastic
11
+ *= require select2/select2.css
11
12
  *= require codemirror
12
13
  *= require codemirror/themes/neat
13
14
  *= require locomotive/toggle.css
@@ -11,6 +11,8 @@
11
11
  font-weight: normal;
12
12
  line-height: 15px;
13
13
 
14
+ height: 400px;
15
+
14
16
  @include background-image(linear-gradient(top, #f0f0f0, #f9f9f9 4px, #f9f9f9 4px, #ffffff 12px, #ffffff));
15
17
 
16
18
  .medium {
@@ -231,7 +231,7 @@ form.formtastic {
231
231
  }
232
232
  } // div.inline-errors
233
233
 
234
- &.string, &.password, &.numeric {
234
+ &.string, &.password, &.numeric, &.select2 {
235
235
  label {
236
236
  padding-top: 2px;
237
237
  }
@@ -264,10 +264,10 @@ form.formtastic {
264
264
 
265
265
  &.text {
266
266
 
267
- &.short textarea {
267
+ textarea {
268
268
  padding: 5px;
269
- height: 28px;
270
269
  width: 696px;
270
+ height: auto;
271
271
  overflow-y: hidden;
272
272
  }
273
273
 
@@ -281,6 +281,20 @@ form.formtastic {
281
281
  }
282
282
  } // li.select_with_edit
283
283
 
284
+ &.select2 {
285
+
286
+ a.select2-choice {
287
+ @include default-input-style;
288
+ padding: 0px 4px;
289
+ @include border-radius(0px);
290
+
291
+ & > div {
292
+ @include border-radius(0px);
293
+ }
294
+ }
295
+
296
+ } // li.select2
297
+
284
298
  &.locale, &.locales {
285
299
  .list {
286
300
  margin-left: 150px;
@@ -13,13 +13,17 @@ module Locomotive
13
13
 
14
14
  before_filter :authorize_content
15
15
 
16
- respond_to :json, only: [:show, :edit, :create, :update, :sort]
16
+ respond_to :json, only: [:index, :show, :edit, :create, :update, :sort]
17
17
 
18
18
  respond_to :csv, only: [:export]
19
19
 
20
20
  def index
21
21
  options = { page: params[:page] || 1, per_page: Locomotive.config.ui[:per_page] }
22
- @content_entries = @content_type.list_or_group_entries(options)
22
+ @content_entries = if params[:q]
23
+ @content_type.ordered_entries(options.merge(q: params[:q]))
24
+ else
25
+ @content_type.list_or_group_entries(options)
26
+ end
23
27
  respond_with @content_entries
24
28
  end
25
29
 
@@ -4,6 +4,8 @@ module Locomotive
4
4
 
5
5
  include Locomotive::Render
6
6
 
7
+ before_filter :set_locale
8
+
7
9
  before_filter :set_content_type
8
10
 
9
11
  before_filter :sanitize_entry_params, only: :create
@@ -21,6 +23,10 @@ module Locomotive
21
23
 
22
24
  protected
23
25
 
26
+ def set_locale
27
+ ::I18n.locale = params[:locale] || current_site.default_locale
28
+ end
29
+
24
30
  def set_content_type
25
31
  @content_type = current_site.content_types.where(slug: params[:slug]).first
26
32
 
@@ -192,5 +192,13 @@ module Locomotive
192
192
  current_site.localized? && current_content_locale.to_s != current_site.default_locale.to_s
193
193
  end
194
194
 
195
+ def localize(object, options = nil)
196
+ if respond_to?(:current_site) && current_site && object.respond_to?(:in_time_zone)
197
+ object = object.in_time_zone(current_site.timezone)
198
+ end
199
+ I18n.localize(object, options)
200
+ end
201
+ alias :l :localize
202
+
195
203
  end
196
204
  end
@@ -10,6 +10,12 @@ module Locomotive
10
10
  [I18n.t("locomotive.locales.#{locale}"), locale]
11
11
  end
12
12
  end
13
+
14
+ def options_for_site_timezones
15
+ ActiveSupport::TimeZone.all.map do |tz|
16
+ [tz, tz.name]
17
+ end
18
+ end
13
19
 
14
20
  end
15
21
  end
@@ -9,13 +9,14 @@ module Locomotive
9
9
  include Extensions::ContentEntry::Csv
10
10
 
11
11
  ## fields ##
12
- field :_slug
12
+ field :_slug, localize: true
13
13
  field :_label_field_name
14
14
  field :_position, type: Integer, default: 0
15
15
  field :_visible, type: Boolean, default: true
16
16
 
17
17
  ## validations ##
18
- validates :_slug, presence: true, uniqueness: { scope: :content_type_id }
18
+ validates_presence_of :_slug
19
+ validates_uniqueness_of :_slug, scope: :content_type_id, allow_blank: true
19
20
 
20
21
  ## associations ##
21
22
  belongs_to :site, class_name: 'Locomotive::Site'
@@ -60,6 +61,7 @@ module Locomotive
60
61
 
61
62
  # Tell if the content entry has been translated or not.
62
63
  # It just checks if the field used for the label has been translated.
64
+ # It assumes the entry is localized.
63
65
  #
64
66
  # @return [ Boolean ] True if translated, false otherwise
65
67
  #
@@ -76,13 +78,22 @@ module Locomotive
76
78
  # @return [ Array ] The list of locales. Nil if not localized
77
79
  #
78
80
  def translated_in
79
- if self.respond_to?(:"#{self._label_field_name}_translations")
81
+ if self.localized?
80
82
  self.send(:"#{self._label_field_name}_translations").keys
81
83
  else
82
84
  nil
83
85
  end
84
86
  end
85
87
 
88
+ # Tell if the entry is localized or not, meaning if the label field
89
+ # is localized or not.
90
+ #
91
+ # @return [ Boolean ] True if localized, false otherwise
92
+ #
93
+ def localized?
94
+ self.respond_to?(:"#{self._label_field_name}_translations")
95
+ end
96
+
86
97
  # Return the next content entry based on the order defined in the parent content type.
87
98
  #
88
99
  # @param [ Object ] The next content entry or nil if not found
@@ -158,7 +169,7 @@ module Locomotive
158
169
  self.class.where(criterion => value).order_by(:order_by.asc).limit(1).first
159
170
  end
160
171
 
161
- # Sets the slug of the instance by using the value of the highlighted field
172
+ # Set the slug of the instance by using the value of the highlighted field
162
173
  # (if available). If a sibling content instance has the same permalink then a
163
174
  # unique one will be generated
164
175
  def set_slug
@@ -168,6 +179,23 @@ module Locomotive
168
179
  self._slug.permalink!
169
180
  self._slug = self.next_unique_slug if self.slug_already_taken?
170
181
  end
182
+
183
+ # all the site locales share the same slug ONLY IF the entry is not localized.
184
+ self.set_same_slug_for_all_site_locales if !self.localized?
185
+ end
186
+
187
+ # For each locale of the site, we set the slug
188
+ # coming from the value for the default locale.
189
+ def set_same_slug_for_all_site_locales
190
+ return unless self.set_site.localized?
191
+
192
+ default_slug = self._slug
193
+
194
+ self.set_site.locales.each do |locale|
195
+ ::Mongoid::Fields::I18n.with_locale(locale) do
196
+ self._slug = default_slug
197
+ end
198
+ end
171
199
  end
172
200
 
173
201
  # Return the next available unique slug as a string
@@ -199,7 +227,9 @@ module Locomotive
199
227
  end
200
228
 
201
229
  def add_to_list_bottom
202
- self._position = self.class.max(:_position).to_i + 1
230
+ unless self.class.empty?
231
+ self._position = self.class.max(:_position).to_i + 1
232
+ end
203
233
  end
204
234
 
205
235
  def send_notifications
@@ -67,9 +67,31 @@ module Locomotive
67
67
  [order_by_attribute, direction]
68
68
  end
69
69
 
70
- def ordered_entries(conditions = {})
71
- _order_by_definition = (conditions || {}).delete(:order_by).try(:split) || self.order_by_definition
72
- self.entries.order_by([_order_by_definition]).where(conditions)
70
+ # Order the list of entries, paginate it if requested
71
+ # and filter it.
72
+ #
73
+ # @param [ Hash ] options Options to filter and paginate.
74
+ #
75
+ # @return [ Criteria ] A Mongoid criteria if not paginated (array otherwise).
76
+ #
77
+ def ordered_entries(options = nil)
78
+ options ||= {}
79
+
80
+ page, per_page = options.delete(:page), options.delete(:per_page)
81
+
82
+ # search for a label
83
+ if options[:q]
84
+ options[label_field_name.to_sym] = /#{options.delete(:q)}/i
85
+ end
86
+
87
+ # order list
88
+ _order_by_definition = (options || {}).delete(:order_by).try(:split) || self.order_by_definition
89
+
90
+ # get list
91
+ _entries = self.entries.order_by([_order_by_definition]).where(options)
92
+
93
+ # pagination or full list
94
+ page ? _entries.page(page).per(per_page) : _entries
73
95
  end
74
96
 
75
97
  def groupable?
@@ -88,11 +110,7 @@ module Locomotive
88
110
  group_by_belongs_to_field(self.group_by_field)
89
111
  end
90
112
  else
91
- if options[:page].nil?
92
- self.ordered_entries
93
- else
94
- self.ordered_entries.page(options[:page]).per(options[:per_page])
95
- end
113
+ self.ordered_entries(options)
96
114
  end
97
115
  end
98
116
 
@@ -70,7 +70,7 @@ module Locomotive
70
70
  end
71
71
 
72
72
  # Copy attributes from an existing editable element coming
73
- # from the parent page. Each editable element may or not
73
+ # from the parent page. Each type of an editable element may or not
74
74
  # override this method. The source element is a new record.
75
75
  #
76
76
  # @param [ EditableElement] el The source element
@@ -80,6 +80,20 @@ module Locomotive
80
80
  self.from_parent = true
81
81
  end
82
82
 
83
+ # Copy the default attributes: _type, hint, fixed, priority and locales
84
+ # from an existing editable element coming from the parent page.
85
+ # Each type of an editable element may or not override this method for
86
+ # options for instance.
87
+ #
88
+ # @param [ EditableElement] el The source element
89
+ #
90
+ def copy_default_attributes_from(el)
91
+ # only the type, hint and fixed properties can be modified from the element
92
+ %w(_type hint fixed priority locales).each do |attr|
93
+ self.send(:"#{attr}=", el.send(attr.to_sym))
94
+ end
95
+ end
96
+
83
97
  # Set the default content from an existing editable element coming
84
98
  # from the parent page. Each editable element may or not
85
99
  # override this method. The source element is an existing record.