locomotive_cms 2.0.0.rc7 → 2.0.0.rc8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. data/Gemfile +6 -4
  2. data/README.textile +4 -3
  3. data/app/assets/images/locomotive/icons/flags/{no.png → nb.png} +0 -0
  4. data/app/assets/javascripts/aloha/plugins/custom/locomotive_media/lib/locomotive_media-plugin.js +1 -1
  5. data/app/assets/javascripts/locomotive/utils/core_ext.js +2 -0
  6. data/app/assets/javascripts/locomotive/views/application_view.js.coffee +7 -0
  7. data/app/assets/javascripts/locomotive/views/content_assets/picker_view.js.coffee +4 -1
  8. data/app/assets/javascripts/locomotive/views/content_entries/_form_view.js.coffee +4 -2
  9. data/app/assets/javascripts/locomotive/views/content_entries/_popup_form_view.js.coffee +8 -3
  10. data/app/assets/javascripts/locomotive/views/content_types/_form_view.js.coffee +0 -2
  11. data/app/assets/javascripts/locomotive/views/content_types/custom_field_entry_view.js.coffee +9 -2
  12. data/app/assets/javascripts/locomotive/views/current_site/edit_view.js.coffee +10 -11
  13. data/app/assets/javascripts/locomotive/views/inline_editor/application_view.js.coffee +9 -0
  14. data/app/assets/javascripts/locomotive/views/pages/_form_view.js.coffee +3 -3
  15. data/app/assets/javascripts/locomotive/views/shared/asset_picker_view.js.coffee +11 -18
  16. data/app/assets/javascripts/locomotive/views/shared/fields/many_to_many_view.js.coffee +0 -4
  17. data/app/assets/javascripts/locomotive/views/shared/form_view.js.coffee +2 -1
  18. data/app/assets/javascripts/locomotive/views/snippets/_form_view.js.coffee +3 -1
  19. data/app/assets/javascripts/locomotive/views/theme_assets/_form_view.js.coffee +4 -4
  20. data/app/assets/javascripts/locomotive/views/theme_assets/image_picker_view.js.coffee +10 -2
  21. data/app/assets/javascripts/tinymce/plugins/locomotive_media/editor_plugin.js +4 -1
  22. data/app/assets/stylesheets/locomotive/backoffice/codemirror_changes.css.scss +1 -0
  23. data/app/assets/stylesheets/locomotive/backoffice/datepicker.css.scss +1 -1
  24. data/app/assets/stylesheets/locomotive/backoffice/dialog_changes.css.scss +9 -3
  25. data/app/assets/stylesheets/locomotive/backoffice/formtastic_changes.css.scss +3 -1
  26. data/app/cells/locomotive/global_actions_cell.rb +1 -1
  27. data/app/controllers/locomotive/api/base_controller.rb +7 -4
  28. data/app/controllers/locomotive/api/content_assets_controller.rb +13 -0
  29. data/app/controllers/locomotive/api/content_types_controller.rb +14 -1
  30. data/app/controllers/locomotive/api/current_site_controller.rb +3 -1
  31. data/app/controllers/locomotive/api/memberships_controller.rb +49 -0
  32. data/app/controllers/locomotive/api/pages_controller.rb +14 -1
  33. data/app/controllers/locomotive/api/sites_controller.rb +44 -0
  34. data/app/controllers/locomotive/api/snippets_controller.rb +14 -1
  35. data/app/controllers/locomotive/api/theme_assets_controller.rb +13 -0
  36. data/app/controllers/locomotive/public/content_entries_controller.rb +7 -3
  37. data/app/helpers/locomotive/content_types_helper.rb +4 -0
  38. data/app/helpers/locomotive/custom_fields_helper.rb +1 -1
  39. data/app/models/locomotive/ability.rb +2 -0
  40. data/app/models/locomotive/content_entry.rb +4 -2
  41. data/app/models/locomotive/content_type.rb +7 -0
  42. data/app/models/locomotive/extensions/content_type/default_values.rb +1 -1
  43. data/app/models/locomotive/extensions/page/redirect.rb +1 -1
  44. data/app/models/locomotive/extensions/page/tree.rb +14 -1
  45. data/app/models/locomotive/site.rb +5 -1
  46. data/app/models/locomotive/theme_asset.rb +1 -1
  47. data/app/presenters/locomotive/membership_presenter.rb +7 -2
  48. data/app/presenters/locomotive/site_presenter.rb +5 -0
  49. data/app/views/locomotive/content_assets/_picker.html.haml +3 -3
  50. data/app/views/locomotive/content_entries/_form.html.haml +1 -1
  51. data/app/views/locomotive/content_types/_form.html.haml +2 -2
  52. data/app/views/locomotive/current_site/_form.html.haml +1 -1
  53. data/app/views/locomotive/custom_fields/types/_many_to_many.html.haml +5 -5
  54. data/app/views/locomotive/my_account/edit.html.haml +1 -1
  55. data/app/views/locomotive/pages/_form.html.haml +1 -1
  56. data/app/views/locomotive/public/pages/show_toolbar.html.haml +2 -2
  57. data/app/views/locomotive/public/sitemaps/show.xml.builder +2 -2
  58. data/app/views/locomotive/shared/_form_actions.html.haml +1 -1
  59. data/app/views/locomotive/shared/_head.html.haml +2 -2
  60. data/app/views/locomotive/snippets/_form.html.haml +1 -1
  61. data/app/views/locomotive/theme_assets/_form.html.haml +1 -1
  62. data/app/views/locomotive/theme_assets/index.html.haml +5 -5
  63. data/config/locales/admin_ui.de.yml +37 -31
  64. data/config/locales/admin_ui.en.yml +1 -1
  65. data/config/locales/admin_ui.es.yml +2 -1
  66. data/config/locales/admin_ui.fr.yml +1 -1
  67. data/config/locales/admin_ui.it.yml +2 -1
  68. data/config/locales/{admin_ui.no.yml → admin_ui.nb.yml} +72 -55
  69. data/config/locales/admin_ui.nl.yml +2 -1
  70. data/config/locales/admin_ui.pt-BR.yml +2 -1
  71. data/config/locales/admin_ui.ru.yml +1 -1
  72. data/config/locales/{carrierwave.no.yml → carrierwave.nb.yml} +1 -1
  73. data/config/locales/default.de.yml +13 -3
  74. data/config/locales/default.en.yml +5 -0
  75. data/config/locales/default.fr.yml +4 -0
  76. data/config/locales/{default.no.yml → default.nb.yml} +43 -1
  77. data/config/locales/{devise.no.yml → devise.nb.yml} +9 -9
  78. data/config/locales/{flash.no.yml → flash.nb.yml} +1 -1
  79. data/config/locales/{formtastic.no.yml → formtastic.nb.yml} +21 -17
  80. data/config/routes.rb +4 -0
  81. data/lib/generators/locomotive/install/templates/locomotive.rb +9 -2
  82. data/lib/locomotive.rb +1 -0
  83. data/lib/locomotive/configuration.rb +4 -3
  84. data/lib/locomotive/custom_fields.rb +2 -0
  85. data/lib/locomotive/liquid/drops/page.rb +1 -1
  86. data/lib/locomotive/liquid/tags/csrf.rb +40 -0
  87. data/lib/locomotive/liquid/tags/extends.rb +3 -9
  88. data/lib/locomotive/liquid/tags/nav.rb +8 -8
  89. data/lib/locomotive/mongoid/patches.rb +54 -9
  90. data/lib/locomotive/rails.rb +1 -0
  91. data/lib/locomotive/rails/action_view.rb +9 -0
  92. data/lib/locomotive/render.rb +4 -4
  93. data/lib/locomotive/version.rb +1 -1
  94. data/vendor/assets/javascripts/locomotive/backbone.modelbinding.js +13 -4
  95. metadata +259 -95
@@ -1,4 +1,4 @@
1
- "no":
1
+ nb:
2
2
  flash:
3
3
  locomotive:
4
4
  pages:
@@ -1,4 +1,4 @@
1
- "no":
1
+ nb:
2
2
  formtastic:
3
3
  titles:
4
4
  information: Generell informasjon
@@ -33,37 +33,40 @@
33
33
  custom_fields:
34
34
  field:
35
35
  name: Alias
36
- import:
37
- new:
38
- source: Fil
39
- samples: Kopier testdata
40
- reset: Reset side
41
- default_site_template: "Bruk standardmalen. Klikk <a href='#'>her</a> for å laste opp en mal fra en zip-fil i stedet."
42
36
  content_type:
43
- item_template: Elementmal
44
- api_accounts: Varslede kontoer
37
+ raw_item_template: Elementmal
38
+ public_submission_enabled: Kan opprettes utenfra
39
+ public_submission_accounts: Kontoer som varsles
40
+ "custom_fields/field":
41
+ select_options: "Valg"
45
42
  content_entry:
46
43
  _slug: Permalink
47
44
  account:
48
45
  edit:
46
+ locale: Språk
49
47
  password: Nytt passord
50
48
  password_confirmation: Bekreft nytt passord
51
49
  page:
52
50
  seo_title: Tittel
51
+ target_klass_name: Modell
52
+ site:
53
+ locales: Språk
53
54
 
54
55
  hints:
55
56
  page:
57
+ handle: "En unik ID for å hente siden fra en ekstern controller"
56
58
  published: "Kun autoriserte kontoer kan se ikke-publiserte sider"
57
59
  cache_strategy: "Buffre siden for å bedre ytelsen. \"Enkel\" er et bra kompromiss."
58
60
  templatized: "Bruk denne siden som mal for en modell."
59
61
  listed: "Styr om siden skal vises i de genererte menyene."
60
- content_type_id: "Innholdstypen denne siden skal være mal for."
62
+ target_klass_name: "Innholdstypen denne siden skal være mal for."
61
63
  seo_title: "Definer en egen tittel for siden. Denne blir benyttet av nettleseren. Hvis denne står tom blir standardverdien fra sideinnstillingene benyttet."
62
64
  meta_keywords: "Overstyr søkemotor-metadata for denne siden. Separer med komma."
63
65
  meta_description: "Overstyr søkemotorbeskrivelsen for denne siden."
64
66
  snippet:
65
67
  slug: "Denne brukes for å inkludere HTML-snutten i en side."
66
68
  site:
69
+ locales: "Dra et flagg til første posisjon for å sette som standard."
67
70
  seo_title: "Definer en global verdi her som brukes som verdi for titteltaggen i sidens head-seksjon."
68
71
  meta_keywords: "Meta-nøkkelord blir brukt i head-seksjonen og leses av søkemotorer. Separeres med komma."
69
72
  meta_description: "Meta-beskrivelse brukes i head-seksjonen og leses av søkemotorer."
@@ -79,10 +82,6 @@
79
82
  source: "Filen er tilgjengelig her: %{url}"
80
83
  update:
81
84
  source: "Filen er tilgjengelig her: %{url}"
82
- custom_fields:
83
- field:
84
- name: "Verdi tilgjengelig i liquid-maler"
85
- hint: "Tekst som vises i skjemaet rett under feltet"
86
85
  content_entry:
87
86
  _slug: "Verdien brukes til å generere en url for en side som fungerer som en mal for denne innholdstypen (f.eks: \"template_page/{{ your_object._permalink }})\"."
88
87
  seo_title: "Verdien benyttes til å erstatte sidetittelen for malen knyttet til modellen. Leses av søkemotorer."
@@ -93,7 +92,12 @@
93
92
  samples: "Vil gjøre at importen kopierer innhold og assets"
94
93
  reset: "Vil gjøre at alle data slettes for den nye siden importeres."
95
94
  content_type:
96
- item_template: "Du kan justere teksten som vises for hvert element i listen. Bruk liquid, f.eks: {{ entry.name }}"
97
- api_enabled: "Brukes for å la sidebrukere opprette ny elementer (f.eks: meldinger i et kontaktskjema)"
98
- api_accounts: "En varslingsepost vil bli sendt til alle kontoene ovenfor når et nytt element blir opprettet."
95
+ name: "Vi foreslår at du bruker flertals form (E.G: Personer)"
96
+ slug: "It will be used as the name of the collection in the liquid templates. Ex: <span class='code'>{{ contents.my_projects }}</span>"
97
+ raw_item_template: "You can customize the text displayed for each item in the list. Simply use Liquid. Ex: <span class='code'>{{ entry.name }})</span>"
98
+ public_submission_enabled: "It is used to let people from outside to create new entries (example: messages in a contact form)"
99
+ public_submission_accounts: "If the public submission option is enabled and for each entry created, sends a notification email to the accounts listed above."
100
+ "custom_fields/field":
101
+ name: "Name of the property for liquid templates. Ex: <span class='code'>&#123;&#123; your_object.&lt;name_of_your_field&gt; &#125;&#125;</span>"
102
+ hint: "Text displayed in the model form just below the field"
99
103
 
data/config/routes.rb CHANGED
@@ -68,6 +68,10 @@ Rails.application.routes.draw do
68
68
 
69
69
  resources :content_entries, :path => 'content_types/:slug/entries'
70
70
 
71
+ resources :sites
72
+
73
+ resources :memberships
74
+
71
75
  resource :current_site, :controller => 'current_site'
72
76
 
73
77
  end
@@ -22,11 +22,11 @@ Locomotive.configure do |config|
22
22
  # :max_content_types => 4
23
23
  # }
24
24
 
25
- # default locale (for now, only en, de, fr, pt-BR and it are supported)
25
+ # default locale (for now, only en, de, fr, pt-BR, it and nb are supported)
26
26
  config.default_locale = :en
27
27
 
28
28
  # available locales suggested to "localize" a site. You will have to pick up at least one among that list.
29
- # config.site_locales = %w{en de fr pt-BR it nl no es ru}
29
+ # config.site_locales = %w{en de fr pt-BR it nl nb es ru}
30
30
 
31
31
  # tell if logs are enabled. Useful for debug purpose.
32
32
  config.enable_logs = true
@@ -48,6 +48,13 @@ Locomotive.configure do |config|
48
48
  # add extra classes other than the defined content types among a site which will potentially used by the templatized pages.
49
49
  # config.models_for_templatization = %w(Product)
50
50
 
51
+ # "Public" forms can be protected from Cross-Site Request Forgery (CSRF) attacks.
52
+ # By default, that protection is disabled (false) in order to keep backwards compatibility with the existing public forms.
53
+ #
54
+ # Note: we strongly recommend to enable it. See the documentation about the "csrf_param" liquid tag.
55
+ #
56
+ # config.csrf_protection = true
57
+
51
58
  # Rack-cache settings, mainly used for the inline resizing image module. Default options:
52
59
  # config.rack_cache = {
53
60
  # :verbose => true,
data/lib/locomotive.rb CHANGED
@@ -12,6 +12,7 @@ require 'locomotive/carrierwave'
12
12
  require 'locomotive/custom_fields'
13
13
  require 'locomotive/httparty'
14
14
  require 'locomotive/action_controller'
15
+ require 'locomotive/rails'
15
16
  require 'locomotive/routing'
16
17
  require 'locomotive/regexps'
17
18
  require 'locomotive/render'
@@ -7,8 +7,8 @@ module Locomotive
7
7
  :reserved_subdomains => %w{www admin email blog webmail mail support help site sites},
8
8
  # :forbidden_paths => %w{layouts snippets stylesheets javascripts assets admin system api},
9
9
  :reserved_slugs => %w{stylesheets javascripts assets admin locomotive images api pages edit},
10
- :locales => %w{en de fr pt-BR it nl no es ru},
11
- :site_locales => %w{en de fr pt-BR it nl no es ru},
10
+ :locales => %w{en de fr pt-BR it nl nb es ru},
11
+ :site_locales => %w{en de fr pt-BR it nl nb es ru},
12
12
  :cookie_key => '_locomotive_session',
13
13
  :enable_logs => false,
14
14
  :delayed_job => false,
@@ -27,7 +27,8 @@ module Locomotive
27
27
  },
28
28
  :devise_modules => [:rememberable, :database_authenticatable, :token_authenticatable, :recoverable, :trackable, :validatable, :encryptable, { :encryptor => :sha1 }],
29
29
  :context_assign_extensions => { },
30
- :models_for_templatization => []
30
+ :models_for_templatization => [],
31
+ :csrf_protection => false
31
32
  }
32
33
 
33
34
  cattr_accessor :settings
@@ -22,6 +22,7 @@ module CustomFields
22
22
  module Types
23
23
 
24
24
  module File
25
+
25
26
  class FileUploader < ::CarrierWave::Uploader::Base
26
27
 
27
28
  # Set correct paths
@@ -34,6 +35,7 @@ module CustomFields
34
35
  end
35
36
 
36
37
  end
38
+
37
39
  end
38
40
 
39
41
  end
@@ -10,7 +10,7 @@ module Locomotive
10
10
  end
11
11
 
12
12
  def slug
13
- self._source.templatized? ? self._source.content_type.slug.singularize : self._source.slug
13
+ self._source.templatized? ? @context['entry']._slug.singularize : self._source.slug
14
14
  end
15
15
 
16
16
  def parent
@@ -0,0 +1,40 @@
1
+ module Locomotive
2
+ module Liquid
3
+ module Tags
4
+ module Csrf
5
+
6
+ class Param < ::Liquid::Tag
7
+
8
+ def render(context)
9
+ controller = context.registers[:controller]
10
+ name = controller.send(:request_forgery_protection_token).to_s
11
+ value = controller.send(:form_authenticity_token)
12
+
13
+ %(<input type="hidden" name="#{name}" value="#{value}" />)
14
+ end
15
+
16
+ end
17
+
18
+ class Meta < ::Liquid::Tag
19
+
20
+ def render(context)
21
+ controller = context.registers[:controller]
22
+ name = controller.send(:request_forgery_protection_token).to_s
23
+ value = controller.send(:form_authenticity_token)
24
+
25
+ %{
26
+ <meta name="csrf-param" content="#{name}" />
27
+ <meta name="csrf-token" content="#{value}" />
28
+ }
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+
35
+ ::Liquid::Template.register_tag('csrf_param', Csrf::Param)
36
+ ::Liquid::Template.register_tag('csrf_meta', Csrf::Meta)
37
+
38
+ end
39
+ end
40
+ end
@@ -18,14 +18,7 @@ module Locomotive
18
18
 
19
19
  def parse_parent_template
20
20
  if @template_name == 'parent'
21
- if @context[:cached_parent]
22
- @context[:parent_page] = @context[:cached_parent] #.clone # parent must not be modified
23
-
24
- @context[:cached_parent].instance_variable_set(:@template, nil) # force to reload the template
25
- @context[:cached_parent] = nil
26
- else
27
- @context[:parent_page] = @context[:page].parent
28
- end
21
+ @context[:parent_page] = @context[:cached_parent] || @context[:page].parent
29
22
  else
30
23
  locale = ::Mongoid::Fields::I18n.locale
31
24
 
@@ -40,7 +33,8 @@ module Locomotive
40
33
 
41
34
  raise PageNotTranslated.new("Page with fullpath '#{@template_name}' was not translated") if parent_template.nil?
42
35
 
43
- @context[:parent_page].instance_variable_set(:@template, parent_template)
36
+ # force the page to restore the original version of its template (from the serialized version)
37
+ @context[:parent_page].instance_variable_set(:@template, nil)
44
38
 
45
39
  parent_template
46
40
  end
@@ -28,7 +28,7 @@ module Locomotive
28
28
  if @options[:snippet]
29
29
  template = @options[:snippet].include?('{') ? @options[:snippet] : context[:site].snippets.where(:slug => @options[:snippet] ).try(:first).try(:template)
30
30
  unless template.blank?
31
- @options[:liquid_render] = ::Liquid::Template.parse( template )
31
+ @options[:liquid_render] = ::Liquid::Template.parse(template)
32
32
  @options[:add_attributes] = ['editable_elements']
33
33
  end
34
34
  end
@@ -70,12 +70,12 @@ module Locomotive
70
70
  @site, @page = context.registers[:site], context.registers[:page]
71
71
 
72
72
  children = (case @source
73
- when 'site' then @site.pages.root.minimal_attributes( @options[:add_attributes] ).first # start from home page
73
+ when 'site' then @site.pages.root.minimal_attributes(@options[:add_attributes]).first # start from home page
74
74
  when 'parent' then @page.parent || @page
75
75
  when 'page' then @page
76
76
  else
77
- @site.pages.fullpath(@source).minimal_attributes( @options[:add_attributes] ).first
78
- end).children_with_minimal_attributes( @options[:add_attributes] ).to_a
77
+ @site.pages.fullpath(@source).minimal_attributes(@options[:add_attributes]).first
78
+ end).children_with_minimal_attributes(@options[:add_attributes]).to_a
79
79
 
80
80
  children.delete_if { |p| !include_page?(p) }
81
81
  end
@@ -86,16 +86,16 @@ module Locomotive
86
86
 
87
87
  icon = @options[:icon] ? '<span></span>' : ''
88
88
 
89
- title = @options[:liquid_render] ? @options[:liquid_render].render( 'page' => page ) : page.title
89
+ title = @options[:liquid_render] ? @options[:liquid_render].render('page' => page) : page.title
90
90
 
91
91
  label = %{#{icon if @options[:icon] != 'after' }#{title}#{icon if @options[:icon] == 'after' }}
92
92
 
93
93
  link_options = caret = ''
94
- href = "/#{page.fullpath}"
94
+ href = File.join('/', @site.localized_page_fullpath(page))
95
95
 
96
96
  if render_children_for_page?(page, depth) && bootstrap?
97
97
  css += ' dropdown'
98
- link_options = %{ class="dropdown-toggle" data-toogle="dropdown"}
98
+ link_options = %{ class="dropdown-toggle" data-toggle="dropdown"}
99
99
  href = '#'
100
100
  caret = %{ <b class="caret"></b>}
101
101
  end
@@ -116,7 +116,7 @@ module Locomotive
116
116
  def render_entry_children(page, depth)
117
117
  output = %{}
118
118
 
119
- children = page.children_with_minimal_attributes( @options[:add_attributes] ).reject { |c| !include_page?(c) }
119
+ children = page.children_with_minimal_attributes(@options[:add_attributes]).reject { |c| !include_page?(c) }
120
120
  if children.present?
121
121
  output = %{<ul id="#{@options[:id]}-#{page.slug.to_s.dasherize}" class="#{bootstrap? ? 'dropdown-menu' : ''}">}
122
122
  children.each do |c, page|
@@ -28,6 +28,13 @@ module Mongoid#:nodoc:
28
28
  end
29
29
  end
30
30
 
31
+ module Criterion
32
+ class Selector < Hash
33
+ # for some reason, the store method behaves differently than the []= one, causing regression bugs (query not localized)
34
+ alias :store :[]=
35
+ end
36
+ end
37
+
31
38
  # without callback feature
32
39
  module Callbacks #:nodoc:
33
40
  module ClassMethods #:nodoc:
@@ -41,21 +48,59 @@ module Mongoid#:nodoc:
41
48
 
42
49
  # make the validators work with localized field
43
50
  module Validations #:nodoc:
44
- def read_attribute_for_validation_with_localization(attr)
45
- if fields[attr.to_s] && fields[attr.to_s].localized?
46
- send(attr.to_sym)
47
- else
48
- read_attribute_for_validation_without_localization(attr)
51
+
52
+ class ExclusionValidator < ActiveModel::Validations::ExclusionValidator
53
+ include Localizable
54
+ end
55
+
56
+ class UniquenessValidator < ActiveModel::EachValidator
57
+
58
+ def to_validate_with_localization(document, attribute, value)
59
+ field = document.fields[attribute.to_s]
60
+ if field.try(:localized?)
61
+ # no need of the translations, just the current value
62
+ value = document.send(attribute.to_sym)
63
+ end
64
+ to_validate_without_localization(document, attribute, value)
65
+ end
66
+
67
+ alias_method_chain :to_validate, :localization
68
+
69
+ end
70
+
71
+ module ClassMethods
72
+ def validates_exclusion_of(*args)
73
+ validates_with(ExclusionValidator, _merge_attributes(args))
49
74
  end
50
75
  end
51
76
 
52
- alias_method_chain :read_attribute_for_validation, :localization
77
+ module LocalizedEachValidator
78
+
79
+ # Performs validation on the supplied record. By default this will call
80
+ # +validates_each+ to determine validity therefore subclasses should
81
+ # override +validates_each+ with validation logic.
82
+ def validate(record)
83
+ attributes.each do |attribute|
84
+ field = record.fields[attribute.to_s]
85
+
86
+ # make sure that we use the localized value and not the translations when we test the allow_nil and allow_blank options
87
+ value = field.try(:localized?) ? record.send(attribute.to_sym) : record.read_attribute_for_validation(attribute)
88
+
89
+ next if (value.nil? && options[:allow_nil]) || (value.blank? && options[:allow_blank])
53
90
 
54
- class PresenceValidator < ActiveModel::EachValidator
55
- def validate_each(document, attribute, value)
56
- document.errors.add(attribute, :blank, options) if value.blank?
91
+ # use the translations of the localized field for the next part
92
+ value = record.read_attribute_for_validation(attribute) if field.try(:localized?)
93
+
94
+ validate_each(record, attribute, value)
95
+ end
57
96
  end
97
+
58
98
  end
99
+
100
+ [FormatValidator, LengthValidator, PresenceValidator, UniquenessValidator, ExclusionValidator].each do |klass|
101
+ klass.send(:include, LocalizedEachValidator)
102
+ end
103
+
59
104
  end
60
105
 
61
106
  end
@@ -0,0 +1 @@
1
+ require 'locomotive/rails/action_view'
@@ -0,0 +1,9 @@
1
+ # http://jfire.io/blog/2012/04/30/how-to-securely-bootstrap-json-in-a-rails-view/
2
+ class ActionView::Base
3
+ def json_escape(s)
4
+ result = s.to_s.gsub('/', '\/')
5
+ s.html_safe? ? result.html_safe : result
6
+ end
7
+
8
+ alias j json_escape
9
+ end
@@ -11,7 +11,7 @@ module Locomotive
11
11
  else
12
12
  @page = locomotive_page
13
13
 
14
- redirect_to(@page.redirect_url) and return if @page.present? && @page.redirect?
14
+ redirect_to(@page.redirect_url, :status => 301) and return if @page.present? && @page.redirect?
15
15
 
16
16
  render_no_page_error and return if @page.nil?
17
17
 
@@ -53,10 +53,10 @@ module Locomotive
53
53
  'url' => request.url,
54
54
  'now' => Time.now.utc,
55
55
  'today' => Date.today,
56
- 'locale' => I18n.locale,
56
+ 'locale' => I18n.locale.to_s,
57
57
  'default_locale' => current_site.default_locale.to_s,
58
58
  'locales' => current_site.locales,
59
- 'current_user' => Locomotive::Liquid::Drops::CurrentUser.new(current_locomotive_account)
59
+ 'current_user' => Locomotive::Liquid::Drops::CurrentUser.new(current_locomotive_account)
60
60
  }
61
61
 
62
62
  assigns.merge!(Locomotive.config.context_assign_extensions)
@@ -64,7 +64,7 @@ module Locomotive
64
64
  assigns.merge!(flash.to_hash.stringify_keys) # data from public submissions
65
65
 
66
66
  if @page.templatized? # add instance from content type
67
- assigns['entry'] = @page.content_entry
67
+ assigns['content_entry'] = assigns['entry'] = @page.content_entry
68
68
  assigns[@page.target_entry_name] = @page.content_entry # just here to help to write readable liquid code
69
69
  end
70
70
 
@@ -1,3 +1,3 @@
1
1
  module Locomotive #:nodoc
2
- VERSION = '2.0.0.rc7'
2
+ VERSION = '2.0.0.rc8'
3
3
  end
@@ -64,10 +64,13 @@ Backbone.ModelBinding = (function(Backbone, _, $){
64
64
  this.modelBindings.push({model: model, eventName: eventName, callback: callback});
65
65
  }
66
66
 
67
- this.registerElementBinding = function(element, callback){
67
+ this.registerElementBinding = function(element, callback, callbackSilently){
68
68
  // bind the form changes to the model
69
69
  element.bind("change", callback);
70
70
  this.elementBindings.push({element: element, eventName: "change", callback: callback});
71
+
72
+ if (callbackSilently)
73
+ element.bind("changeSilently", callbackSilently)
71
74
  }
72
75
  }
73
76
 
@@ -188,18 +191,24 @@ Backbone.ModelBinding = (function(Backbone, _, $){
188
191
  element.val(val);
189
192
  };
190
193
 
191
- var setModelValue = function(attr_name, value){
194
+ var setModelValue = function(attr_name, value, silent){
195
+ if (typeof(silent) === 'undefined' || silent == null) silent = false
192
196
  var data = {};
193
197
  data[attr_name] = value;
194
- model.set(data);
198
+ model.set(data, { 'silent': silent });
195
199
  };
196
200
 
197
201
  var elementChange = function(ev){
198
202
  setModelValue(attribute_name, view.$(ev.target).val());
199
203
  };
200
204
 
205
+ // FIXME (Did): simple solution to update the model without triggering related callbacks (solving a bug with tinymce)
206
+ var elementChangeSilently = function(ev) {
207
+ setModelValue(attribute_name, view.$(ev.target).val(), true);
208
+ }
209
+
201
210
  modelBinder.registerModelBinding(model, attribute_name, modelChange);
202
- modelBinder.registerElementBinding(element, elementChange);
211
+ modelBinder.registerElementBinding(element, elementChange, elementChangeSilently);
203
212
 
204
213
  // set the default value on the form, from the model
205
214
  var attr_value = model.get(attribute_name);