locomotive_cms 2.0.0.rc2 → 2.0.0.rc4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. data/README.textile +4 -4
  2. data/app/assets/images/locomotive/icons/start.png +0 -0
  3. data/app/assets/javascripts/locomotive/models/page.js.coffee +1 -1
  4. data/app/assets/javascripts/locomotive/models/site.js.coffee +1 -1
  5. data/app/assets/javascripts/locomotive/views/content_entries/_form_view.js.coffee +11 -4
  6. data/app/assets/javascripts/locomotive/views/editable_elements/control_view.js.coffee +24 -0
  7. data/app/assets/javascripts/locomotive/views/editable_elements/edit_all_view.js.coffee +4 -0
  8. data/app/assets/javascripts/locomotive/views/editable_elements/short_text_view.js.coffee +5 -0
  9. data/app/assets/javascripts/locomotive/views/pages/_form_view.js.coffee +19 -0
  10. data/app/assets/javascripts/locomotive/views/shared/fields/has_many_view.js.coffee +3 -0
  11. data/app/assets/javascripts/locomotive/views/shared/fields/many_to_many_view.js.coffee +3 -0
  12. data/app/assets/javascripts/locomotive/views/shared/form_view.js.coffee +6 -0
  13. data/app/assets/stylesheets/locomotive/backoffice/application.css.scss +8 -0
  14. data/app/assets/stylesheets/locomotive/inline_editor/layout.css.scss +1 -0
  15. data/app/controllers/locomotive/pages_controller.rb +4 -3
  16. data/app/helpers/locomotive/pages_helper.rb +13 -0
  17. data/app/models/locomotive/editable_control.rb +56 -0
  18. data/app/models/locomotive/editable_element.rb +90 -18
  19. data/app/models/locomotive/editable_file.rb +63 -1
  20. data/app/models/locomotive/editable_long_text.rb +2 -0
  21. data/app/models/locomotive/editable_short_text.rb +32 -5
  22. data/app/models/locomotive/extensions/page/editable_elements.rb +14 -45
  23. data/app/models/locomotive/extensions/page/listed.rb +1 -0
  24. data/app/models/locomotive/extensions/page/parse.rb +10 -3
  25. data/app/models/locomotive/extensions/page/render.rb +80 -0
  26. data/app/models/locomotive/extensions/page/templatized.rb +43 -2
  27. data/app/models/locomotive/extensions/site/subdomain_domains.rb +1 -0
  28. data/app/models/locomotive/page.rb +7 -1
  29. data/app/models/locomotive/site.rb +4 -0
  30. data/app/presenters/locomotive/content_entry_presenter.rb +1 -1
  31. data/app/presenters/locomotive/editable_control_presenter.rb +18 -0
  32. data/app/presenters/locomotive/page_presenter.rb +2 -2
  33. data/app/views/locomotive/pages/_editable_elements.html.haml +12 -0
  34. data/app/views/locomotive/pages/_form.html.haml +6 -4
  35. data/app/views/locomotive/pages/_page.html.haml +3 -0
  36. data/app/views/locomotive/shared/menu/_contents.html.haml +1 -1
  37. data/config/locales/admin_ui.fr.yml +29 -3
  38. data/config/locales/default.en.yml +1 -1
  39. data/config/locales/default.fr.yml +23 -16
  40. data/config/locales/formtastic.en.yml +1 -7
  41. data/config/locales/formtastic.fr.yml +7 -14
  42. data/lib/locomotive.rb +1 -1
  43. data/lib/locomotive/engine.rb +8 -8
  44. data/lib/locomotive/liquid.rb +1 -0
  45. data/lib/locomotive/liquid/drops/content_entry.rb +2 -2
  46. data/lib/locomotive/liquid/drops/page.rb +1 -1
  47. data/lib/locomotive/liquid/errors.rb +2 -0
  48. data/lib/locomotive/liquid/filters/base.rb +47 -0
  49. data/lib/locomotive/liquid/filters/html.rb +16 -76
  50. data/lib/locomotive/liquid/filters/misc.rb +43 -18
  51. data/lib/locomotive/liquid/filters/text.rb +18 -0
  52. data/lib/locomotive/liquid/tags/editable.rb +1 -1
  53. data/lib/locomotive/liquid/tags/editable/base.rb +15 -24
  54. data/lib/locomotive/liquid/tags/editable/control.rb +31 -0
  55. data/lib/locomotive/liquid/tags/editable/file.rb +17 -1
  56. data/lib/locomotive/liquid/tags/editable/long_text.rb +5 -3
  57. data/lib/locomotive/liquid/tags/editable/short_text.rb +9 -3
  58. data/lib/locomotive/liquid/tags/extends.rb +3 -1
  59. data/lib/locomotive/liquid/tags/locale_switcher.rb +2 -2
  60. data/lib/locomotive/liquid/tags/nav.rb +26 -7
  61. data/lib/locomotive/liquid/tags/paginate.rb +9 -2
  62. data/lib/locomotive/middlewares.rb +2 -1
  63. data/lib/locomotive/middlewares/inline_editor.rb +31 -0
  64. data/lib/locomotive/render.rb +5 -29
  65. data/lib/locomotive/version.rb +1 -1
  66. data/vendor/assets/javascripts/locomotive/cmd.js +31 -0
  67. data/vendor/assets/javascripts/locomotive/menu_toggler.js +1 -1
  68. metadata +89 -74
  69. data/app/middlewares/locomotive/inline_editor_middleware.rb +0 -24
  70. data/lib/locomotive/liquid/tags/blueprint.rb +0 -21
  71. data/lib/locomotive/liquid/tags/editable/content.rb +0 -49
  72. data/lib/locomotive/liquid/tags/jquery.rb +0 -17
@@ -1,5 +1,6 @@
1
1
  require 'locomotive/liquid/drops/base'
2
2
  require 'locomotive/liquid/drops/proxy_collection'
3
+ require 'locomotive/liquid/filters/base'
3
4
 
4
5
  %w{. tags drops filters}.each do |dir|
5
6
  Dir[File.join(File.dirname(__FILE__), 'liquid', dir, '*.rb')].each { |lib| require lib }
@@ -45,7 +45,7 @@ module Locomotive
45
45
  if not @@forbidden_attributes.include?(meth.to_s)
46
46
  value = self._source.send(meth)
47
47
 
48
- if value.respond_to?(:all)
48
+ if value.respond_to?(:all) # check for an association
49
49
  filter_and_order_list(value)
50
50
  else
51
51
  value
@@ -70,7 +70,7 @@ module Locomotive
70
70
  end
71
71
  else
72
72
  list.ordered
73
- end.all
73
+ end
74
74
  end
75
75
 
76
76
  end
@@ -6,7 +6,7 @@ module Locomotive
6
6
  delegate :seo_title, :meta_keywords, :meta_description, :to => '_source'
7
7
 
8
8
  def title
9
- self._source.templatized? ? @context['content_entry']._label : self._source.title
9
+ self._source.templatized? ? @context['entry']._label : self._source.title
10
10
  end
11
11
 
12
12
  def slug
@@ -1,5 +1,7 @@
1
1
  module Locomotive
2
2
  module Liquid
3
3
  class PageNotFound < ::Liquid::Error; end
4
+
5
+ class PageNotTranslated < ::Liquid::Error; end
4
6
  end
5
7
  end
@@ -0,0 +1,47 @@
1
+ module Locomotive
2
+ module Liquid
3
+ module Filters
4
+ module Base
5
+
6
+ protected
7
+
8
+ # Convert an array of properties ('key:value') into a hash
9
+ # Ex: ['width:50', 'height:100'] => { :width => '50', :height => '100' }
10
+ def args_to_options(*args)
11
+ options = {}
12
+ args.flatten.each do |a|
13
+ if (a =~ /^(.*):(.*)$/)
14
+ options[$1.to_sym] = $2
15
+ end
16
+ end
17
+ options
18
+ end
19
+
20
+ # Write options (Hash) into a string according to the following pattern:
21
+ # <key1>="<value1>", <key2>="<value2", ...etc
22
+ def inline_options(options = {})
23
+ return '' if options.empty?
24
+ (options.stringify_keys.sort.to_a.collect { |a, b| "#{a}=\"#{b}\"" }).join(' ') << ' '
25
+ end
26
+
27
+ # Get the url to be used in html tags such as image_tag, flash_tag, ...etc
28
+ # input: url (String) OR asset drop
29
+ def get_url_from_asset(input)
30
+ input.respond_to?(:url) ? input.url : input
31
+ end
32
+
33
+ def asset_url(path)
34
+ ThemeAssetUploader.url_for(@context.registers[:site], path)
35
+ end
36
+
37
+ def absolute_url(url)
38
+ url.starts_with?('/') ? url : "/#{url}"
39
+ end
40
+
41
+ end
42
+
43
+ ::Liquid::Template.register_filter(Base)
44
+
45
+ end
46
+ end
47
+ end
@@ -3,7 +3,21 @@ module Locomotive
3
3
  module Filters
4
4
  module Html
5
5
 
6
- # Write the url to a stylesheet resource
6
+ # Returns a link tag that browsers and news readers can use to auto-detect an RSS or ATOM feed.
7
+ # input: url of the feed
8
+ # example:
9
+ # {{ '/foo/bar' | auto_discovery_link_tag: 'rel:alternate', 'type:application/atom+xml', 'title:A title' }}
10
+ def auto_discovery_link_tag(input, *args)
11
+ options = args_to_options(args)
12
+
13
+ rel = options[:rel] || 'alternate'
14
+ type = options[:type] || Mime::Type.lookup_by_extension('rss').to_s
15
+ title = options[:title] || 'RSS'
16
+
17
+ %{<link rel="#{rel}" type="#{type}" title="#{title}" href="#{input}" />}
18
+ end
19
+
20
+ # Write the url of a theme stylesheet
7
21
  # input: name of the css file
8
22
  def stylesheet_url(input)
9
23
  return '' if input.nil?
@@ -17,7 +31,7 @@ module Locomotive
17
31
  input
18
32
  end
19
33
 
20
- # Write the link to a stylesheet resource
34
+ # Write the link tag of a theme stylesheet
21
35
  # input: url of the css file
22
36
  def stylesheet_tag(input, media = 'screen')
23
37
  return '' if input.nil?
@@ -92,80 +106,6 @@ module Locomotive
92
106
  }.gsub(/ >/, '>').strip
93
107
  end
94
108
 
95
- # Render the navigation for a paginated collection
96
- def default_pagination(paginate, *args)
97
- return '' if paginate['parts'].empty?
98
-
99
- options = args_to_options(args)
100
-
101
- previous_label = options[:previous_label] || I18n.t('pagination.previous')
102
- next_label = options[:next_label] || I18n.t('pagination.next')
103
-
104
- previous_link = (if paginate['previous'].blank?
105
- "<span class=\"disabled prev_page\">#{previous_label}</span>"
106
- else
107
- "<a href=\"#{absolute_url(paginate['previous']['url'])}\" class=\"prev_page\">#{previous_label}</a>"
108
- end)
109
-
110
- links = ""
111
- paginate['parts'].each do |part|
112
- links << (if part['is_link']
113
- "<a href=\"#{absolute_url(part['url'])}\">#{part['title']}</a>"
114
- elsif part['hellip_break']
115
- "<span class=\"gap\">#{part['title']}</span>"
116
- else
117
- "<span class=\"current\">#{part['title']}</span>"
118
- end)
119
- end
120
-
121
- next_link = (if paginate['next'].blank?
122
- "<span class=\"disabled next_page\">#{next_label}</span>"
123
- else
124
- "<a href=\"#{absolute_url(paginate['next']['url'])}\" class=\"next_page\">#{next_label}</a>"
125
- end)
126
-
127
- %{<div class="pagination #{options[:css]}">
128
- #{previous_link}
129
- #{links}
130
- #{next_link}
131
- </div>}
132
- end
133
-
134
- protected
135
-
136
- # Convert an array of properties ('key:value') into a hash
137
- # Ex: ['width:50', 'height:100'] => { :width => '50', :height => '100' }
138
- def args_to_options(*args)
139
- options = {}
140
- args.flatten.each do |a|
141
- if (a =~ /^(.*):(.*)$/)
142
- options[$1.to_sym] = $2
143
- end
144
- end
145
- options
146
- end
147
-
148
- # Write options (Hash) into a string according to the following pattern:
149
- # <key1>="<value1>", <key2>="<value2", ...etc
150
- def inline_options(options = {})
151
- return '' if options.empty?
152
- (options.stringify_keys.sort.to_a.collect { |a, b| "#{a}=\"#{b}\"" }).join(' ') << ' '
153
- end
154
-
155
- # Get the url to be used in html tags such as image_tag, flash_tag, ...etc
156
- # input: url (String) OR asset drop
157
- def get_url_from_asset(input)
158
- input.respond_to?(:url) ? input.url : input
159
- end
160
-
161
- def asset_url(path)
162
- ThemeAssetUploader.url_for(@context.registers[:site], path)
163
- end
164
-
165
- def absolute_url(url)
166
- url.starts_with?('/') ? url : "/#{url}"
167
- end
168
-
169
109
  end
170
110
 
171
111
  ::Liquid::Template.register_filter(Html)
@@ -3,24 +3,6 @@ module Locomotive
3
3
  module Filters
4
4
  module Misc
5
5
 
6
- def underscore(input)
7
- input.to_s.gsub(' ', '_').gsub('/', '_').underscore
8
- end
9
-
10
- def dasherize(input)
11
- input.to_s.gsub(' ', '-').gsub('/', '-').dasherize
12
- end
13
-
14
- def multi_line(input)
15
- input.to_s.gsub("\n", '<br/>')
16
- end
17
-
18
- def concat(input, *args)
19
- result = input.to_s
20
- args.flatten.each { |a| result << a.to_s }
21
- result
22
- end
23
-
24
6
  def modulo(word, index, modulo)
25
7
  (index.to_i + 1) % modulo == 0 ? word : ''
26
8
  end
@@ -33,6 +15,49 @@ module Locomotive
33
15
  input.last
34
16
  end
35
17
 
18
+ def default(input, value)
19
+ input.blank? ? value : input
20
+ end
21
+
22
+ # Render the navigation for a paginated collection
23
+ def default_pagination(paginate, *args)
24
+ return '' if paginate['parts'].empty?
25
+
26
+ options = args_to_options(args)
27
+
28
+ previous_label = options[:previous_label] || I18n.t('pagination.previous')
29
+ next_label = options[:next_label] || I18n.t('pagination.next')
30
+
31
+ previous_link = (if paginate['previous'].blank?
32
+ "<span class=\"disabled prev_page\">#{previous_label}</span>"
33
+ else
34
+ "<a href=\"#{absolute_url(paginate['previous']['url'])}\" class=\"prev_page\">#{previous_label}</a>"
35
+ end)
36
+
37
+ links = ""
38
+ paginate['parts'].each do |part|
39
+ links << (if part['is_link']
40
+ "<a href=\"#{absolute_url(part['url'])}\">#{part['title']}</a>"
41
+ elsif part['hellip_break']
42
+ "<span class=\"gap\">#{part['title']}</span>"
43
+ else
44
+ "<span class=\"current\">#{part['title']}</span>"
45
+ end)
46
+ end
47
+
48
+ next_link = (if paginate['next'].blank?
49
+ "<span class=\"disabled next_page\">#{next_label}</span>"
50
+ else
51
+ "<a href=\"#{absolute_url(paginate['next']['url'])}\" class=\"next_page\">#{next_label}</a>"
52
+ end)
53
+
54
+ %{<div class="pagination #{options[:css]}">
55
+ #{previous_link}
56
+ #{links}
57
+ #{next_link}
58
+ </div>}
59
+ end
60
+
36
61
  end
37
62
 
38
63
  ::Liquid::Template.register_filter(Misc)
@@ -3,6 +3,24 @@ module Locomotive
3
3
  module Filters
4
4
  module Text
5
5
 
6
+ def underscore(input)
7
+ input.to_s.gsub(' ', '_').gsub('/', '_').underscore
8
+ end
9
+
10
+ def dasherize(input)
11
+ input.to_s.gsub(' ', '-').gsub('/', '-').dasherize
12
+ end
13
+
14
+ def multi_line(input)
15
+ input.to_s.gsub("\n", '<br/>')
16
+ end
17
+
18
+ def concat(input, *args)
19
+ result = input.to_s
20
+ args.flatten.each { |a| result << a.to_s }
21
+ result
22
+ end
23
+
6
24
  def textile(input)
7
25
  ::RedCloth.new(input).to_html
8
26
  end
@@ -2,4 +2,4 @@ require 'locomotive/liquid/tags/editable/base'
2
2
  require 'locomotive/liquid/tags/editable/short_text'
3
3
  require 'locomotive/liquid/tags/editable/long_text'
4
4
  require 'locomotive/liquid/tags/editable/file'
5
- require 'locomotive/liquid/tags/editable/content'
5
+ require 'locomotive/liquid/tags/editable/control'
@@ -9,7 +9,7 @@ module Locomotive
9
9
  def initialize(tag_name, markup, tokens, context)
10
10
  if markup =~ Syntax
11
11
  @slug = $1.gsub('\'', '')
12
- @options = { :assignable => true }
12
+ @options = { :fixed => false }
13
13
  markup.scan(::Liquid::TagAttributes) { |key, value| @options[key.to_sym] = value.gsub(/^'/, '').gsub(/'$/, '') }
14
14
  else
15
15
  raise ::Liquid::SyntaxError.new("Syntax Error in 'editable_xxx' - Valid syntax: editable_xxx <slug>(, <options>)")
@@ -22,18 +22,7 @@ module Locomotive
22
22
  super
23
23
 
24
24
  if @context[:page].present?
25
- @context[:page].add_or_update_editable_element({
26
- :block => @context[:current_block].try(:name),
27
- :slug => @slug,
28
- :hint => @options[:hint],
29
- :priority => @options[:priority] || 0,
30
- :default_attribute => @options[:default],
31
- :default_content => default_content_option,
32
- :assignable => @options[:assignable],
33
- :disabled => false,
34
- :from_parent => false,
35
- :_type => self.document_type.to_s
36
- }, document_type)
25
+ @context[:page].add_or_update_editable_element(default_element_attributes, document_type)
37
26
  end
38
27
  end
39
28
 
@@ -43,9 +32,6 @@ module Locomotive
43
32
  element = current_page.find_editable_element(context['block'].try(:name), @slug)
44
33
 
45
34
  if element.present?
46
- unless element.default_content.present?
47
- element.default_content = render_default_content(context)
48
- end
49
35
  render_element(context, element)
50
36
  else
51
37
  Locomotive.log :error, "[editable element] missing element `#{context['block'].try(:name)}` / #{@slug} on #{current_page.fullpath}"
@@ -55,6 +41,19 @@ module Locomotive
55
41
 
56
42
  protected
57
43
 
44
+ def default_element_attributes
45
+ {
46
+ :block => @options[:block] || @context[:current_block].try(:name),
47
+ :slug => @slug,
48
+ :hint => @options[:hint],
49
+ :priority => @options[:priority] || 0,
50
+ :fixed => !!@options[:fixed],
51
+ :disabled => false,
52
+ :from_parent => false,
53
+ :_type => self.document_type.to_s
54
+ }
55
+ end
56
+
58
57
  def render_element(element)
59
58
  raise 'FIXME: has to be overidden'
60
59
  end
@@ -63,14 +62,6 @@ module Locomotive
63
62
  raise 'FIXME: has to be overidden'
64
63
  end
65
64
 
66
- def default_content_option
67
- result = nil
68
- if @options[:default].present?
69
- result = @context[:page].send(@options[:default])
70
- end
71
- result
72
- end
73
-
74
65
  def render_default_content(context)
75
66
  render_all(@nodelist, context).join(' ')
76
67
  end
@@ -0,0 +1,31 @@
1
+ module Locomotive
2
+ module Liquid
3
+ module Tags
4
+ module Editable
5
+ class Control < Base
6
+
7
+ protected
8
+
9
+ def default_element_attributes
10
+ if @nodelist.first.is_a?(String)
11
+ super.merge(:content => @nodelist.first.try(:to_s), :options => @options[:options])
12
+ else
13
+ super
14
+ end
15
+ end
16
+
17
+ def render_element(context, element)
18
+ element.content
19
+ end
20
+
21
+ def document_type
22
+ EditableControl
23
+ end
24
+
25
+ end
26
+
27
+ ::Liquid::Template.register_tag('editable_control', Control)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -6,8 +6,24 @@ module Locomotive
6
6
 
7
7
  protected
8
8
 
9
+ def default_element_attributes
10
+ if @nodelist.first.is_a?(String)
11
+ super.merge(:default_source_url => @nodelist.first.try(:to_s))
12
+ else
13
+ super
14
+ end
15
+ end
16
+
9
17
  def render_element(context, element)
10
- element.source? ? element.source.url : element.default_content
18
+ if element.source?
19
+ element.source.url
20
+ else
21
+ if element.default_source_url.present?
22
+ element.default_source_url
23
+ else
24
+ render_default_content(context)
25
+ end
26
+ end
11
27
  end
12
28
 
13
29
  def document_type