From 5dfbb2bdb72dbc7716d7539deb740218c41d00fc Mon Sep 17 00:00:00 2001 From: did Date: Sun, 8 Jan 2012 16:17:31 -0800 Subject: [PATCH 1/4] upgrade to the last version of delayed_job_mongoid gem + remove reference to the previous handlebars-rails gem (just add the js file instead) + refactor the way to display the list of content types in the back-office menu --- Gemfile | 5 +- Gemfile.lock | 101 +- app/assets/javascripts/locomotive.js | 1 - app/helpers/locomotive/base_helper.rb | 8 - .../locomotive/content_types_helper.rb | 135 +- app/models/locomotive/content_entry.rb | 2 +- app/models/locomotive/page.rb | 2 +- .../shared/menu/_contents.html.haml | 45 +- doc/TODO | 2 +- .../install/templates/locomotive.rb | 5 +- lib/locomotive/configuration.rb | 5 +- spec/dummy/config/initializers/locomotive.rb | 5 +- vendor/assets/javascripts/handlebars.js | 1493 +++++++++++++++++ 13 files changed, 1620 insertions(+), 189 deletions(-) create mode 100644 vendor/assets/javascripts/handlebars.js diff --git a/Gemfile b/Gemfile index 66d0eef7..8b200243 100644 --- a/Gemfile +++ b/Gemfile @@ -24,7 +24,7 @@ gem 'coffee-script', '~> 2.2.0' gem 'uglifier', '~> 1.0.4' gem 'jquery-rails', '~> 1.0.16' gem 'rails-backbone', '0.5.4' -gem 'handlebars-rails', :git => 'git://github.com/yabawock/handlebars-rails.git' +# gem 'handlebars-rails', :git => 'git://github.com/yabawock/handlebars-rails.git' gem 'codemirror-rails' gem 'tinymce-rails' gem 'flash_cookie_session', '~> 1.1.1' @@ -47,8 +47,7 @@ gem 'rubyzip' gem 'actionmailer-with-request', '~> 0.3.0', :require => 'actionmailer_with_request' gem 'httparty', '~> 0.8.1' -gem 'delayed_job', '~> 3.0.0.pre4' -gem 'delayed_job_mongoid', '~> 1.0.7' +gem 'delayed_job_mongoid', '~> 1.0.8' gem 'SystemTimer', :platforms => :ruby_18 # The rest of the dependencies are for use when in the locomotive dev environment diff --git a/Gemfile.lock b/Gemfile.lock index 71d5cf9f..e36053b2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,27 +1,22 @@ GIT remote: git://github.com/chriseppstein/compass.git - revision: 79d94647f9a00b06c4a83db02e86f5d404569baf + revision: bffba483754cb9381fa51efd8e2a1f0482a21ac6 specs: - compass (0.12.alpha.1.79d9464) + compass (0.12.alpha.4.bffba48) chunky_png (~> 1.2) fssm (>= 0.2.7) sass (~> 3.1) GIT remote: git://github.com/plataformatec/devise.git - revision: ede004169c6af7416f8c4e3fc29a653bee133f60 + revision: a949f9eca24f9d43f516363fbf2f5d004623355e specs: - devise (1.5.1) + devise (2.0.0.rc) bcrypt-ruby (~> 3.0) orm_adapter (~> 0.0.3) + railties (~> 3.1) warden (~> 1.1) -GIT - remote: git://github.com/yabawock/handlebars-rails.git - revision: a09077aa91f10e08403af84586b2f2f0b38d9e2f - specs: - handlebars-rails (0.9.1) - GIT remote: git@github.com:locomotivecms/mongoid_acts_as_tree.git revision: ca494d22c3d7946385aba1153c017d9c30e9f9d3 @@ -39,7 +34,7 @@ PATH GEM remote: http://rubygems.org/ specs: - RedCloth (4.2.8) + RedCloth (4.2.9) SystemTimer (1.2.3) ZenTest (4.6.2) actionmailer (3.1.3) @@ -77,7 +72,7 @@ GEM autotest (4.4.6) ZenTest (>= 4.4.1) bcrypt-ruby (3.0.1) - bson (1.4.0) + bson (1.5.2) bson_ext (1.4.0) builder (3.0.0) bushido (0.0.35) @@ -98,44 +93,43 @@ GEM carrierwave-mongoid (0.1.3) carrierwave (>= 0.5.6) mongoid (~> 2.1) - cells (3.7.0) + cells (3.7.1) actionpack (~> 3.0) railties (~> 3.0) - childprocess (0.2.2) + childprocess (0.2.6) ffi (~> 1.0.6) chunky_png (1.2.5) - codemirror-rails (0.3.1) + codemirror-rails (0.3.2) + railties (~> 3.0) coffee-script (2.2.0) coffee-script-source execjs - coffee-script-source (1.1.3) - cucumber (1.1.3) + coffee-script-source (1.2.0) + cucumber (1.1.4) builder (>= 2.1.2) diff-lcs (>= 1.1.2) - gherkin (~> 2.6.7) + gherkin (~> 2.7.1) json (>= 1.4.6) term-ansicolor (>= 1.0.6) - cucumber-rails (1.2.0) - capybara (>= 1.1.1) - cucumber (>= 1.1.1) + cucumber-rails (1.2.1) + capybara (>= 1.1.2) + cucumber (>= 1.1.3) nokogiri (>= 1.5.0) - daemons (1.0.10) database_cleaner (0.7.0) - delayed_job (3.0.0.pre4) + delayed_job (3.0.0) activesupport (~> 3.0) - daemons (= 1.0.10) - delayed_job_mongoid (1.0.7) - delayed_job (~> 3.0.0.pre) + delayed_job_mongoid (1.0.8) + delayed_job (~> 3.0.0) mongoid (>= 2.0) diff-lcs (1.1.3) - dragonfly (0.9.8) + dragonfly (0.9.9) rack ejs (1.0.0) erubis (2.7.0) - excon (0.7.8) - execjs (1.2.9) + excon (0.7.12) + execjs (1.2.13) multi_json (~> 1.0) - factory_girl (2.3.1) + factory_girl (2.3.2) activesupport factory_girl_rails (1.4.0) factory_girl (~> 2.3.0) @@ -156,25 +150,26 @@ GEM formatador (0.2.1) formtastic (2.0.2) rails (~> 3.0) - fssm (0.2.7) - gherkin (2.6.8) + fssm (0.2.8.1) + gherkin (2.7.2) json (>= 1.4.6) growl-glue (1.0.7) - haml (3.1.3) - highline (1.6.8) + haml (3.1.4) + highline (1.6.9) hike (1.2.1) httparty (0.8.1) multi_json multi_xml i18n (0.6.0) - jquery-rails (1.0.18) + jquery-rails (1.0.19) railties (~> 3.0) thor (~> 0.14) - json (1.6.1) - json_pure (1.6.1) - kaminari (0.12.4) - rails (>= 3.0.0) - kgio (2.6.0) + json (1.6.4) + kaminari (0.13.0) + actionpack (>= 3.0.0) + activesupport (>= 3.0.0) + railties (>= 3.0.0) + kgio (2.7.2) launchy (2.0.5) addressable (~> 2.2.6) locomotive_liquid (2.2.2) @@ -185,13 +180,13 @@ GEM mime-types (1.17.2) mimetype-fu (0.1.2) mocha (0.9.12) - mongo (1.4.0) - bson (= 1.4.0) + mongo (1.5.2) + bson (= 1.5.2) mongoid (2.3.4) activemodel (~> 3.1) mongo (~> 1.3) tzinfo (~> 0.3.22) - multi_json (1.0.3) + multi_json (1.0.4) multi_xml (0.4.1) net-scp (1.0.4) net-ssh (>= 1.99.1) @@ -202,7 +197,7 @@ GEM cucumber (>= 0.8) rake polyglot (0.3.3) - rack (1.3.5) + rack (1.3.6) rack-cache (1.1) rack (>= 0.4) rack-mount (0.8.3) @@ -232,7 +227,7 @@ GEM thor (~> 0.14.6) raindrops (0.8.0) rake (0.9.2) - rdoc (3.11) + rdoc (3.12) json (~> 1.4) responders (0.6.4) rest-client (1.6.7) @@ -242,7 +237,7 @@ GEM rspec-core (~> 2.6.0) rspec-expectations (~> 2.6.0) rspec-mocks (~> 2.6.0) - rspec-cells (0.1.0) + rspec-cells (0.1.1) rails (~> 3.0) rspec-rails (~> 2.2) rspec-core (2.6.4) @@ -255,19 +250,19 @@ GEM railties (~> 3.0) rspec (~> 2.6.0) ruby-hmac (0.4.0) - rubyzip (0.9.4) + rubyzip (0.9.5) sanitize (2.0.3) nokogiri (>= 1.4.4, < 1.6) - sass (3.1.10) + sass (3.1.12) sass-rails (3.1.5) actionpack (~> 3.1.0) railties (~> 3.1.0) sass (~> 3.1.10) tilt (~> 1.3.2) - selenium-webdriver (2.13.0) - childprocess (>= 0.2.1) + selenium-webdriver (2.16.0) + childprocess (>= 0.2.5) ffi (~> 1.0.9) - json_pure + multi_json (~> 1.0.4) rubyzip sprockets (2.0.3) hike (~> 1.2) @@ -315,8 +310,7 @@ DEPENDENCIES cucumber-rails custom_fields! database_cleaner - delayed_job (~> 3.0.0.pre4) - delayed_job_mongoid (~> 1.0.7) + delayed_job_mongoid (~> 1.0.8) devise! dragonfly (~> 0.9.8) factory_girl_rails (~> 1.1) @@ -325,7 +319,6 @@ DEPENDENCIES formtastic (~> 2.0.2) growl-glue haml (~> 3.1.3) - handlebars-rails! highline (~> 1.6.2) httparty (~> 0.8.1) jquery-rails (~> 1.0.16) diff --git a/app/assets/javascripts/locomotive.js b/app/assets/javascripts/locomotive.js index 177c602a..80a27763 100644 --- a/app/assets/javascripts/locomotive.js +++ b/app/assets/javascripts/locomotive.js @@ -8,7 +8,6 @@ //= require jquery-ui //= require jquery_ujs //= require underscore -//= require handlebars //= require backbone //= require codemirror //= require tinymce-jquery diff --git a/app/helpers/locomotive/base_helper.rb b/app/helpers/locomotive/base_helper.rb index d3deec9d..3b765e4e 100644 --- a/app/helpers/locomotive/base_helper.rb +++ b/app/helpers/locomotive/base_helper.rb @@ -36,14 +36,6 @@ module Locomotive::BaseHelper end end - # def collection_to_js(collection, options = {}) # FIXME: DEPRECATED - # js = collection.collect { |object| object.to_json } - # - # options_to_js = ActiveSupport::JSON.encode(options).gsub(/^\{/, '').gsub(/\}$/, '') - # - # "new Object({ \"collection\": [#{js.join(', ')}], #{options_to_js} })" - # end - def flash_message if not flash.empty? first_key = flash.keys.first diff --git a/app/helpers/locomotive/content_types_helper.rb b/app/helpers/locomotive/content_types_helper.rb index 5c23e9b1..5817b566 100644 --- a/app/helpers/locomotive/content_types_helper.rb +++ b/app/helpers/locomotive/content_types_helper.rb @@ -1,23 +1,50 @@ module Locomotive::ContentTypesHelper - def each_content_type_menu_item(&block) - current_site.content_types.ordered.only(:site_id, :name, :slug, :label_field_name).each do |content_type| - next unless content_type.persisted? + # Iterates over the content types with the following rules + # - content types are ordered by the updated_at date (DESC) + # - each content type has its own submenu if saved recently + # - if there are more than ui.max_content_types content types, the extra ones go under "..." + # - if a content type is selected and it is part of the extra content types, then + # it will be moved to the first position in the displayed list (with its own submenu) + # + # @param [ Block ] block The statements responsible to display the menu item from a content type or a list of content types + # + def each_content_type(&block) + visible, others = [], [] - item_on = (content_type.slug == @content_type.slug) rescue nil + current_site.content_types.ordered.only(:site_id, :name, :slug, :label_field_name).each_with_index do |content_type, index| + next if !content_type.persisted? - label = truncate(content_type.name, :length => 15) - url = content_entries_url(content_type.slug) - css = @content_type && content_type.slug == @content_type.slug ? 'on' : '' - - html = submenu_entry(label, url, :i18n => false, :css => css) do - yield(content_type) + if index >= Locomotive.config.ui.max_content_types + if self.is_content_type_selected(content_type) + others << visible.delete_at(Locomotive.config.ui.max_content_types - 1) # swap content types + visible.insert(0, content_type) + else + others << content_type # fills the "..." menu + end + next end - haml_concat(html) + visible << content_type end + + visible.map { |c| yield(c) } + yield(others) end + def is_content_type_selected(content_type) + @content_type && content_type.slug == @content_type.slug + end + + # Renders the label of a content type entry. If no raw_item_template filled in the content type, + # it just calls the _label method of the entry (based on the label_field_id). Otherwise, it + # parses and renders the liquid template. + # + # @param [ ContentType ] content_type The content type for better performance + # @param [ ContentEntry] entry The entry we want to display the label + # + # @return [ String ] The label of the content type entry + # def entry_label(content_type, entry) if content_type.raw_item_template.blank? entry._label # default one @@ -34,90 +61,4 @@ module Locomotive::ContentTypesHelper end end - # MAX_DISPLAYED_CONTENTS = 4 - # - # def fetch_content_types - # return @content_types if @content_types - # - # @content_types = current_site.content_types.ordered. - # limit(:contents => Locomotive.config.lastest_items_nb). - # only(:site_id, :name, :slug, :highlighted_field_name, :contents_custom_fields_version, :order_by, :serialized_item_template, :raw_item_template).to_a - # - # if @content_type && @content_type.persisted? && @content_types.index(@content_type) >= MAX_DISPLAYED_CONTENTS - # @content_types.delete(@content_type) - # @content_types.insert(0, @content_type) - # end - # - # # be sure, we've got the custom klass up-to-date, otherwise it will fail miserably - # @content_types.each do |content_type| - # if content_type.content_klass_out_of_date? - # content_type.reload - # content_type.invalidate_content_klass - # end - # end - # - # @content_types - # end - # - # def each_content_type_menu_item(which = :first, &block) - # types = fetch_content_types - # sliced = [] - # - # if which == :first - # sliced = types[0..MAX_DISPLAYED_CONTENTS - 1] - # elsif types.size > MAX_DISPLAYED_CONTENTS - # sliced = types[MAX_DISPLAYED_CONTENTS, types.size - MAX_DISPLAYED_CONTENTS] - # end - # - # return [] if sliced.empty? - # - # sliced.each do |content_type| - # next if content_type.new_record? - # item_on = (content_type.slug == @content_type.slug) rescue nil - # - # label = truncate(content_type.name, :length => 15) - # url = contents_url(content_type.slug) - # css = @content_type && content_type.slug == @content_type.slug ? 'on' : '' - # - # html = submenu_entry(label, url, :i18n => false, :css => css) do - # yield(content_type) - # end - # - # haml_concat(html) - # end - # end - # - # def other_content_types(&block) - # types = fetch_content_types - # - # if types.size > MAX_DISPLAYED_CONTENTS - # sliced = types[MAX_DISPLAYED_CONTENTS, types.size - MAX_DISPLAYED_CONTENTS] - # - # html = submenu_entry('...', '#', :i18n => false) do - # yield(sliced) - # end - # - # haml_concat(html) - # end - # end - # - # def content_label_for(content) - # if content._parent.raw_item_template.blank? - # content._label # default one - # else - # assigns = { - # 'site' => current_site, - # 'content' => content.to_liquid - # } - # - # registers = { - # :controller => self, - # :site => current_site, - # :current_locomotive_account => current_locomotive_account - # } - # - # preserve(content._parent.item_template.render(::Liquid::Context.new({}, assigns, registers))) - # end - # end - end diff --git a/app/models/locomotive/content_entry.rb b/app/models/locomotive/content_entry.rb index 82a08801..c5f710d3 100644 --- a/app/models/locomotive/content_entry.rb +++ b/app/models/locomotive/content_entry.rb @@ -27,7 +27,7 @@ module Locomotive ## named scopes ## scope :visible, :where => { :_visible => true } - scope :latest_updated, :order_by => :updated_at.desc, :limit => Locomotive.config.lastest_entries_nb + scope :latest_updated, :order_by => :updated_at.desc, :limit => Locomotive.config.ui.lastest_entries_nb ## methods ## diff --git a/app/models/locomotive/page.rb b/app/models/locomotive/page.rb index ed935878..7717863f 100644 --- a/app/models/locomotive/page.rb +++ b/app/models/locomotive/page.rb @@ -41,7 +41,7 @@ module Locomotive validates_exclusion_of :slug, :in => Locomotive.config.reserved_slugs, :if => Proc.new { |p| p.depth == 0 } ## named scopes ## - scope :latest_updated, :order_by => [[:updated_at, :desc]], :limit => Locomotive.config.lastest_entries_nb + scope :latest_updated, :order_by => [[:updated_at, :desc]], :limit => Locomotive.config.ui.lastest_entries_nb scope :root, :where => { :slug => 'index', :depth => 0 } scope :not_found, :where => { :slug => '404', :depth => 0 } scope :published, :where => { :published => true } diff --git a/app/views/locomotive/shared/menu/_contents.html.haml b/app/views/locomotive/shared/menu/_contents.html.haml index be496066..cee89362 100644 --- a/app/views/locomotive/shared/menu/_contents.html.haml +++ b/app/views/locomotive/shared/menu/_contents.html.haml @@ -11,25 +11,30 @@ = link_to truncate(page.title, :length => 25), edit_page_url(page) %span= time_ago_in_words(page.updated_at) -- each_content_type_menu_item do |content_type| - .wrapper - .header - %p= link_to t('locomotive.content_entries.index.new'), new_content_entry_url(content_type.slug) +- each_content_type do |menu_item| + -if menu_item.is_a?(Array) + - content_types = menu_item + = submenu_entry '...', '#', :i18n => false do + .wrapper + .inner + %ul.big-links + - content_types.each do |content_type| + %li + = link_to truncate(content_type.name, :length => 20), content_entries_url(content_type.slug) + - else + - content_type = menu_item + = submenu_entry truncate(content_type.name, :length => 15), content_entries_url(content_type.slug), :i18n => false, :css => "#{'on' if is_content_type_selected(content_type)}" do + .wrapper + .header + %p= link_to t('locomotive.content_entries.index.new'), new_content_entry_url(content_type.slug) - - if can? :manage, content_type - %p.edit= link_to t('locomotive.content_entries.index.edit'), edit_content_type_url(content_type) + - if can? :manage, content_type + %p.edit= link_to t('locomotive.content_types.index.edit'), edit_content_type_url(content_type) - .inner - %h2!= t('locomotive.content_entries.index.lastest_entries') - %ul - - content_type.entries.latest_updated.each do |entry| - %li - = link_to truncate(entry._label(content_type), :length => 20), edit_content_entry_url(content_type.slug, entry) - %span= time_ago_in_words(entry.updated_at) - -/ - other_content_types do |content_types| -/ .inner -/ %ul.big-links -/ - content_types.each do |content_type| -/ %li -/ = link_to truncate(content_type.name, :length => 20), contents_url(content_type.slug) \ No newline at end of file + .inner + %h2!= t('locomotive.content_entries.index.lastest_entries') + %ul + - content_type.entries.latest_updated.each do |entry| + %li + = link_to truncate(entry._label(content_type), :length => 20), edit_content_entry_url(content_type.slug, entry) + %span= time_ago_in_words(entry.updated_at) \ No newline at end of file diff --git a/doc/TODO b/doc/TODO index 57a38894..754e9c0b 100644 --- a/doc/TODO +++ b/doc/TODO @@ -49,7 +49,7 @@ x edit my site x show / hide options of a field based on its type x select: add/edit/remove options x text: formatting - - change in main menu + x change in main menu x manage contents x list (highlighted field) x slugify diff --git a/lib/generators/locomotive/install/templates/locomotive.rb b/lib/generators/locomotive/install/templates/locomotive.rb index 0a265832..c443d8a9 100644 --- a/lib/generators/locomotive/install/templates/locomotive.rb +++ b/lib/generators/locomotive/install/templates/locomotive.rb @@ -44,7 +44,10 @@ Locomotive.configure do |config| config.delayed_job = false # configure how many items we display in sub menu in the "Contents" section. - # config.lastest_entries_nb = 5 + # config.ui = { + # :lastest_entries_nb => 5, + # :max_content_types => 1 + # } # default locale (for now, only en, de, fr, pt-BR and it are supported) config.default_locale = :en diff --git a/lib/locomotive/configuration.rb b/lib/locomotive/configuration.rb index e2e30036..f9614c20 100644 --- a/lib/locomotive/configuration.rb +++ b/lib/locomotive/configuration.rb @@ -16,7 +16,10 @@ module Locomotive :mailer_sender => 'support@example.com', :manage_subdomain => false, :manage_manage_domains => false, - :lastest_entries_nb => 5, + :ui => { + :lastest_entries_nb => 5, + :max_content_types => 1 # TODO 4 + }, :rack_cache => { :verbose => true, :metastore => URI.encode("file:#{Rails.root}/tmp/dragonfly/cache/meta"), # URI encoded in case of spaces diff --git a/spec/dummy/config/initializers/locomotive.rb b/spec/dummy/config/initializers/locomotive.rb index c735b76a..12b82e07 100644 --- a/spec/dummy/config/initializers/locomotive.rb +++ b/spec/dummy/config/initializers/locomotive.rb @@ -45,7 +45,10 @@ Locomotive.configure do |config| config.delayed_job = true # false # configure how many items we display in sub menu in the "Contents" section. - # config.lastest_entries_nb = 5 + # config.ui = { + # :lastest_entries_nb => 5, + # :max_content_types => 1 + # } # default locale (for now, only en, de, fr, pt-BR and it are supported) config.default_locale = :en diff --git a/vendor/assets/javascripts/handlebars.js b/vendor/assets/javascripts/handlebars.js new file mode 100644 index 00000000..592a0866 --- /dev/null +++ b/vendor/assets/javascripts/handlebars.js @@ -0,0 +1,1493 @@ +// lib/handlebars/parser.js +/* Jison generated parser */ +var handlebars = (function(){ +var parser = {trace: function trace() { }, +yy: {}, +symbols_: {"error":2,"root":3,"program":4,"EOF":5,"statements":6,"simpleInverse":7,"statement":8,"openInverse":9,"closeBlock":10,"openBlock":11,"mustache":12,"partial":13,"CONTENT":14,"COMMENT":15,"OPEN_BLOCK":16,"inMustache":17,"CLOSE":18,"OPEN_INVERSE":19,"OPEN_ENDBLOCK":20,"path":21,"OPEN":22,"OPEN_UNESCAPED":23,"OPEN_PARTIAL":24,"params":25,"hash":26,"param":27,"STRING":28,"INTEGER":29,"BOOLEAN":30,"hashSegments":31,"hashSegment":32,"ID":33,"EQUALS":34,"pathSegments":35,"SEP":36,"$accept":0,"$end":1}, +terminals_: {2:"error",5:"EOF",14:"CONTENT",15:"COMMENT",16:"OPEN_BLOCK",18:"CLOSE",19:"OPEN_INVERSE",20:"OPEN_ENDBLOCK",22:"OPEN",23:"OPEN_UNESCAPED",24:"OPEN_PARTIAL",28:"STRING",29:"INTEGER",30:"BOOLEAN",33:"ID",34:"EQUALS",36:"SEP"}, +productions_: [0,[3,2],[4,3],[4,1],[4,0],[6,1],[6,2],[8,3],[8,3],[8,1],[8,1],[8,1],[8,1],[11,3],[9,3],[10,3],[12,3],[12,3],[13,3],[13,4],[7,2],[17,3],[17,2],[17,2],[17,1],[25,2],[25,1],[27,1],[27,1],[27,1],[27,1],[26,1],[31,2],[31,1],[32,3],[32,3],[32,3],[32,3],[21,1],[35,3],[35,1]], +performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) { + +var $0 = $$.length - 1; +switch (yystate) { +case 1: return $$[$0-1] +break; +case 2: this.$ = new yy.ProgramNode($$[$0-2], $$[$0]) +break; +case 3: this.$ = new yy.ProgramNode($$[$0]) +break; +case 4: this.$ = new yy.ProgramNode([]) +break; +case 5: this.$ = [$$[$0]] +break; +case 6: $$[$0-1].push($$[$0]); this.$ = $$[$0-1] +break; +case 7: this.$ = new yy.InverseNode($$[$0-2], $$[$0-1], $$[$0]) +break; +case 8: this.$ = new yy.BlockNode($$[$0-2], $$[$0-1], $$[$0]) +break; +case 9: this.$ = $$[$0] +break; +case 10: this.$ = $$[$0] +break; +case 11: this.$ = new yy.ContentNode($$[$0]) +break; +case 12: this.$ = new yy.CommentNode($$[$0]) +break; +case 13: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1]) +break; +case 14: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1]) +break; +case 15: this.$ = $$[$0-1] +break; +case 16: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1]) +break; +case 17: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1], true) +break; +case 18: this.$ = new yy.PartialNode($$[$0-1]) +break; +case 19: this.$ = new yy.PartialNode($$[$0-2], $$[$0-1]) +break; +case 20: +break; +case 21: this.$ = [[$$[$0-2]].concat($$[$0-1]), $$[$0]] +break; +case 22: this.$ = [[$$[$0-1]].concat($$[$0]), null] +break; +case 23: this.$ = [[$$[$0-1]], $$[$0]] +break; +case 24: this.$ = [[$$[$0]], null] +break; +case 25: $$[$0-1].push($$[$0]); this.$ = $$[$0-1]; +break; +case 26: this.$ = [$$[$0]] +break; +case 27: this.$ = $$[$0] +break; +case 28: this.$ = new yy.StringNode($$[$0]) +break; +case 29: this.$ = new yy.IntegerNode($$[$0]) +break; +case 30: this.$ = new yy.BooleanNode($$[$0]) +break; +case 31: this.$ = new yy.HashNode($$[$0]) +break; +case 32: $$[$0-1].push($$[$0]); this.$ = $$[$0-1] +break; +case 33: this.$ = [$$[$0]] +break; +case 34: this.$ = [$$[$0-2], $$[$0]] +break; +case 35: this.$ = [$$[$0-2], new yy.StringNode($$[$0])] +break; +case 36: this.$ = [$$[$0-2], new yy.IntegerNode($$[$0])] +break; +case 37: this.$ = [$$[$0-2], new yy.BooleanNode($$[$0])] +break; +case 38: this.$ = new yy.IdNode($$[$0]) +break; +case 39: $$[$0-2].push($$[$0]); this.$ = $$[$0-2]; +break; +case 40: this.$ = [$$[$0]] +break; +} +}, +table: [{3:1,4:2,5:[2,4],6:3,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],24:[1,15]},{1:[3]},{5:[1,16]},{5:[2,3],7:17,8:18,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,19],20:[2,3],22:[1,13],23:[1,14],24:[1,15]},{5:[2,5],14:[2,5],15:[2,5],16:[2,5],19:[2,5],20:[2,5],22:[2,5],23:[2,5],24:[2,5]},{4:20,6:3,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,4],22:[1,13],23:[1,14],24:[1,15]},{4:21,6:3,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,4],22:[1,13],23:[1,14],24:[1,15]},{5:[2,9],14:[2,9],15:[2,9],16:[2,9],19:[2,9],20:[2,9],22:[2,9],23:[2,9],24:[2,9]},{5:[2,10],14:[2,10],15:[2,10],16:[2,10],19:[2,10],20:[2,10],22:[2,10],23:[2,10],24:[2,10]},{5:[2,11],14:[2,11],15:[2,11],16:[2,11],19:[2,11],20:[2,11],22:[2,11],23:[2,11],24:[2,11]},{5:[2,12],14:[2,12],15:[2,12],16:[2,12],19:[2,12],20:[2,12],22:[2,12],23:[2,12],24:[2,12]},{17:22,21:23,33:[1,25],35:24},{17:26,21:23,33:[1,25],35:24},{17:27,21:23,33:[1,25],35:24},{17:28,21:23,33:[1,25],35:24},{21:29,33:[1,25],35:24},{1:[2,1]},{6:30,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],24:[1,15]},{5:[2,6],14:[2,6],15:[2,6],16:[2,6],19:[2,6],20:[2,6],22:[2,6],23:[2,6],24:[2,6]},{17:22,18:[1,31],21:23,33:[1,25],35:24},{10:32,20:[1,33]},{10:34,20:[1,33]},{18:[1,35]},{18:[2,24],21:40,25:36,26:37,27:38,28:[1,41],29:[1,42],30:[1,43],31:39,32:44,33:[1,45],35:24},{18:[2,38],28:[2,38],29:[2,38],30:[2,38],33:[2,38],36:[1,46]},{18:[2,40],28:[2,40],29:[2,40],30:[2,40],33:[2,40],36:[2,40]},{18:[1,47]},{18:[1,48]},{18:[1,49]},{18:[1,50],21:51,33:[1,25],35:24},{5:[2,2],8:18,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,2],22:[1,13],23:[1,14],24:[1,15]},{14:[2,20],15:[2,20],16:[2,20],19:[2,20],22:[2,20],23:[2,20],24:[2,20]},{5:[2,7],14:[2,7],15:[2,7],16:[2,7],19:[2,7],20:[2,7],22:[2,7],23:[2,7],24:[2,7]},{21:52,33:[1,25],35:24},{5:[2,8],14:[2,8],15:[2,8],16:[2,8],19:[2,8],20:[2,8],22:[2,8],23:[2,8],24:[2,8]},{14:[2,14],15:[2,14],16:[2,14],19:[2,14],20:[2,14],22:[2,14],23:[2,14],24:[2,14]},{18:[2,22],21:40,26:53,27:54,28:[1,41],29:[1,42],30:[1,43],31:39,32:44,33:[1,45],35:24},{18:[2,23]},{18:[2,26],28:[2,26],29:[2,26],30:[2,26],33:[2,26]},{18:[2,31],32:55,33:[1,56]},{18:[2,27],28:[2,27],29:[2,27],30:[2,27],33:[2,27]},{18:[2,28],28:[2,28],29:[2,28],30:[2,28],33:[2,28]},{18:[2,29],28:[2,29],29:[2,29],30:[2,29],33:[2,29]},{18:[2,30],28:[2,30],29:[2,30],30:[2,30],33:[2,30]},{18:[2,33],33:[2,33]},{18:[2,40],28:[2,40],29:[2,40],30:[2,40],33:[2,40],34:[1,57],36:[2,40]},{33:[1,58]},{14:[2,13],15:[2,13],16:[2,13],19:[2,13],20:[2,13],22:[2,13],23:[2,13],24:[2,13]},{5:[2,16],14:[2,16],15:[2,16],16:[2,16],19:[2,16],20:[2,16],22:[2,16],23:[2,16],24:[2,16]},{5:[2,17],14:[2,17],15:[2,17],16:[2,17],19:[2,17],20:[2,17],22:[2,17],23:[2,17],24:[2,17]},{5:[2,18],14:[2,18],15:[2,18],16:[2,18],19:[2,18],20:[2,18],22:[2,18],23:[2,18],24:[2,18]},{18:[1,59]},{18:[1,60]},{18:[2,21]},{18:[2,25],28:[2,25],29:[2,25],30:[2,25],33:[2,25]},{18:[2,32],33:[2,32]},{34:[1,57]},{21:61,28:[1,62],29:[1,63],30:[1,64],33:[1,25],35:24},{18:[2,39],28:[2,39],29:[2,39],30:[2,39],33:[2,39],36:[2,39]},{5:[2,19],14:[2,19],15:[2,19],16:[2,19],19:[2,19],20:[2,19],22:[2,19],23:[2,19],24:[2,19]},{5:[2,15],14:[2,15],15:[2,15],16:[2,15],19:[2,15],20:[2,15],22:[2,15],23:[2,15],24:[2,15]},{18:[2,34],33:[2,34]},{18:[2,35],33:[2,35]},{18:[2,36],33:[2,36]},{18:[2,37],33:[2,37]}], +defaultActions: {16:[2,1],37:[2,23],53:[2,21]}, +parseError: function parseError(str, hash) { + throw new Error(str); +}, +parse: function parse(input) { + var self = this, + stack = [0], + vstack = [null], // semantic value stack + lstack = [], // location stack + table = this.table, + yytext = '', + yylineno = 0, + yyleng = 0, + recovering = 0, + TERROR = 2, + EOF = 1; + + //this.reductionCount = this.shiftCount = 0; + + this.lexer.setInput(input); + this.lexer.yy = this.yy; + this.yy.lexer = this.lexer; + if (typeof this.lexer.yylloc == 'undefined') + this.lexer.yylloc = {}; + var yyloc = this.lexer.yylloc; + lstack.push(yyloc); + + if (typeof this.yy.parseError === 'function') + this.parseError = this.yy.parseError; + + function popStack (n) { + stack.length = stack.length - 2*n; + vstack.length = vstack.length - n; + lstack.length = lstack.length - n; + } + + function lex() { + var token; + token = self.lexer.lex() || 1; // $end = 1 + // if token isn't its numeric value, convert + if (typeof token !== 'number') { + token = self.symbols_[token] || token; + } + return token; + }; + + var symbol, preErrorSymbol, state, action, a, r, yyval={},p,len,newState, expected; + while (true) { + // retreive state number from top of stack + state = stack[stack.length-1]; + + // use default actions if available + if (this.defaultActions[state]) { + action = this.defaultActions[state]; + } else { + if (symbol == null) + symbol = lex(); + // read action for current state and first input + action = table[state] && table[state][symbol]; + } + + // handle parse error + if (typeof action === 'undefined' || !action.length || !action[0]) { + + if (!recovering) { + // Report error + expected = []; + for (p in table[state]) if (this.terminals_[p] && p > 2) { + expected.push("'"+this.terminals_[p]+"'"); + } + var errStr = ''; + if (this.lexer.showPosition) { + errStr = 'Parse error on line '+(yylineno+1)+":\n"+this.lexer.showPosition()+'\nExpecting '+expected.join(', '); + } else { + errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " + + (symbol == 1 /*EOF*/ ? "end of input" : + ("'"+(this.terminals_[symbol] || symbol)+"'")); + } + this.parseError(errStr, + {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected}); + } + + // just recovered from another error + if (recovering == 3) { + if (symbol == EOF) { + throw new Error(errStr || 'Parsing halted.'); + } + + // discard current lookahead and grab another + yyleng = this.lexer.yyleng; + yytext = this.lexer.yytext; + yylineno = this.lexer.yylineno; + yyloc = this.lexer.yylloc; + symbol = lex(); + } + + // try to recover from error + while (1) { + // check for error recovery rule in this state + if ((TERROR.toString()) in table[state]) { + break; + } + if (state == 0) { + throw new Error(errStr || 'Parsing halted.'); + } + popStack(1); + state = stack[stack.length-1]; + } + + preErrorSymbol = symbol; // save the lookahead token + symbol = TERROR; // insert generic error symbol as new lookahead + state = stack[stack.length-1]; + action = table[state] && table[state][TERROR]; + recovering = 3; // allow 3 real symbols to be shifted before reporting a new error + } + + // this shouldn't happen, unless resolve defaults are off + if (action[0] instanceof Array && action.length > 1) { + throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol); + } + + switch (action[0]) { + + case 1: // shift + //this.shiftCount++; + + stack.push(symbol); + vstack.push(this.lexer.yytext); + lstack.push(this.lexer.yylloc); + stack.push(action[1]); // push state + symbol = null; + if (!preErrorSymbol) { // normal execution/no error + yyleng = this.lexer.yyleng; + yytext = this.lexer.yytext; + yylineno = this.lexer.yylineno; + yyloc = this.lexer.yylloc; + if (recovering > 0) + recovering--; + } else { // error just occurred, resume old lookahead f/ before error + symbol = preErrorSymbol; + preErrorSymbol = null; + } + break; + + case 2: // reduce + //this.reductionCount++; + + len = this.productions_[action[1]][1]; + + // perform semantic action + yyval.$ = vstack[vstack.length-len]; // default to $$ = $1 + // default location, uses first token for firsts, last for lasts + yyval._$ = { + first_line: lstack[lstack.length-(len||1)].first_line, + last_line: lstack[lstack.length-1].last_line, + first_column: lstack[lstack.length-(len||1)].first_column, + last_column: lstack[lstack.length-1].last_column + }; + r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack); + + if (typeof r !== 'undefined') { + return r; + } + + // pop off stack + if (len) { + stack = stack.slice(0,-1*len*2); + vstack = vstack.slice(0, -1*len); + lstack = lstack.slice(0, -1*len); + } + + stack.push(this.productions_[action[1]][0]); // push nonterminal (reduce) + vstack.push(yyval.$); + lstack.push(yyval._$); + // goto new state = table[STATE][NONTERMINAL] + newState = table[stack[stack.length-2]][stack[stack.length-1]]; + stack.push(newState); + break; + + case 3: // accept + return true; + } + + } + + return true; +}};/* Jison generated lexer */ +var lexer = (function(){var lexer = ({EOF:1, +parseError:function parseError(str, hash) { + if (this.yy.parseError) { + this.yy.parseError(str, hash); + } else { + throw new Error(str); + } + }, +setInput:function (input) { + this._input = input; + this._more = this._less = this.done = false; + this.yylineno = this.yyleng = 0; + this.yytext = this.matched = this.match = ''; + this.conditionStack = ['INITIAL']; + this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0}; + return this; + }, +input:function () { + var ch = this._input[0]; + this.yytext+=ch; + this.yyleng++; + this.match+=ch; + this.matched+=ch; + var lines = ch.match(/\n/); + if (lines) this.yylineno++; + this._input = this._input.slice(1); + return ch; + }, +unput:function (ch) { + this._input = ch + this._input; + return this; + }, +more:function () { + this._more = true; + return this; + }, +pastInput:function () { + var past = this.matched.substr(0, this.matched.length - this.match.length); + return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, ""); + }, +upcomingInput:function () { + var next = this.match; + if (next.length < 20) { + next += this._input.substr(0, 20-next.length); + } + return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, ""); + }, +showPosition:function () { + var pre = this.pastInput(); + var c = new Array(pre.length + 1).join("-"); + return pre + this.upcomingInput() + "\n" + c+"^"; + }, +next:function () { + if (this.done) { + return this.EOF; + } + if (!this._input) this.done = true; + + var token, + match, + col, + lines; + if (!this._more) { + this.yytext = ''; + this.match = ''; + } + var rules = this._currentRules(); + for (var i=0;i < rules.length; i++) { + match = this._input.match(this.rules[rules[i]]); + if (match) { + lines = match[0].match(/\n.*/g); + if (lines) this.yylineno += lines.length; + this.yylloc = {first_line: this.yylloc.last_line, + last_line: this.yylineno+1, + first_column: this.yylloc.last_column, + last_column: lines ? lines[lines.length-1].length-1 : this.yylloc.last_column + match[0].length} + this.yytext += match[0]; + this.match += match[0]; + this.matches = match; + this.yyleng = this.yytext.length; + this._more = false; + this._input = this._input.slice(match[0].length); + this.matched += match[0]; + token = this.performAction.call(this, this.yy, this, rules[i],this.conditionStack[this.conditionStack.length-1]); + if (token) return token; + else return; + } + } + if (this._input === "") { + return this.EOF; + } else { + this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(), + {text: "", token: null, line: this.yylineno}); + } + }, +lex:function lex() { + var r = this.next(); + if (typeof r !== 'undefined') { + return r; + } else { + return this.lex(); + } + }, +begin:function begin(condition) { + this.conditionStack.push(condition); + }, +popState:function popState() { + return this.conditionStack.pop(); + }, +_currentRules:function _currentRules() { + return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules; + }}); +lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) { + +var YYSTATE=YY_START +switch($avoiding_name_collisions) { +case 0: this.begin("mu"); if (yy_.yytext) return 14; +break; +case 1: return 14; +break; +case 2: return 24; +break; +case 3: return 16; +break; +case 4: return 20; +break; +case 5: return 19; +break; +case 6: return 19; +break; +case 7: return 23; +break; +case 8: return 23; +break; +case 9: yy_.yytext = yy_.yytext.substr(3,yy_.yyleng-5); this.begin("INITIAL"); return 15; +break; +case 10: return 22; +break; +case 11: return 34; +break; +case 12: return 33; +break; +case 13: return 33; +break; +case 14: return 36; +break; +case 15: /*ignore whitespace*/ +break; +case 16: this.begin("INITIAL"); return 18; +break; +case 17: this.begin("INITIAL"); return 18; +break; +case 18: yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2).replace(/\\"/g,'"'); return 28; +break; +case 19: return 30; +break; +case 20: return 30; +break; +case 21: return 29; +break; +case 22: return 33; +break; +case 23: return 'INVALID'; +break; +case 24: return 5; +break; +} +}; +lexer.rules = [/^[^\x00]*?(?=(\{\{))/,/^[^\x00]+/,/^\{\{>/,/^\{\{#/,/^\{\{\//,/^\{\{\^/,/^\{\{\s*else\b/,/^\{\{\{/,/^\{\{&/,/^\{\{![\s\S]*?\}\}/,/^\{\{/,/^=/,/^\.(?=[} ])/,/^\.\./,/^[/.]/,/^\s+/,/^\}\}\}/,/^\}\}/,/^"(\\["]|[^"])*"/,/^true(?=[}\s])/,/^false(?=[}\s])/,/^[0-9]+(?=[}\s])/,/^[a-zA-Z0-9_$-]+(?=[=}\s/.])/,/^./,/^$/]; +lexer.conditions = {"mu":{"rules":[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24],"inclusive":false},"INITIAL":{"rules":[0,1,24],"inclusive":true}};return lexer;})() +parser.lexer = lexer; +return parser; +})(); +if (typeof require !== 'undefined' && typeof exports !== 'undefined') { +exports.parser = handlebars; +exports.parse = function () { return handlebars.parse.apply(handlebars, arguments); } +exports.main = function commonjsMain(args) { + if (!args[1]) + throw new Error('Usage: '+args[0]+' FILE'); + if (typeof process !== 'undefined') { + var source = require('fs').readFileSync(require('path').join(process.cwd(), args[1]), "utf8"); + } else { + var cwd = require("file").path(require("file").cwd()); + var source = cwd.join(args[1]).read({charset: "utf-8"}); + } + return exports.parser.parse(source); +} +if (typeof module !== 'undefined' && require.main === module) { + exports.main(typeof process !== 'undefined' ? process.argv.slice(1) : require("system").args); +} +}; +; +// lib/handlebars/base.js +var Handlebars = {}; + +Handlebars.VERSION = "1.0.beta.2"; + +Handlebars.Parser = handlebars; + +Handlebars.parse = function(string) { + Handlebars.Parser.yy = Handlebars.AST; + return Handlebars.Parser.parse(string); +}; + +Handlebars.print = function(ast) { + return new Handlebars.PrintVisitor().accept(ast); +}; + +Handlebars.helpers = {}; +Handlebars.partials = {}; + +Handlebars.registerHelper = function(name, fn, inverse) { + if(inverse) { fn.not = inverse; } + this.helpers[name] = fn; +}; + +Handlebars.registerPartial = function(name, str) { + this.partials[name] = str; +}; + +Handlebars.registerHelper('helperMissing', function(arg) { + if(arguments.length === 2) { + return undefined; + } else { + throw new Error("Could not find property '" + arg + "'"); + } +}); + +Handlebars.registerHelper('blockHelperMissing', function(context, fn, inverse) { + inverse = inverse || function() {}; + + var ret = ""; + var type = Object.prototype.toString.call(context); + + if(type === "[object Function]") { + context = context(); + } + + if(context === true) { + return fn(this); + } else if(context === false || context == null) { + return inverse(this); + } else if(type === "[object Array]") { + if(context.length > 0) { + for(var i=0, j=context.length; i 0) { + for(var i=0, j=context.length; i": ">", + '"': """, + "'": "'", + "`": "`" + }; + + var badChars = /&(?!\w+;)|[<>"'`]/g; + var possible = /[&<>"'`]/; + + var escapeChar = function(chr) { + return escape[chr] || "&" + }; + + Handlebars.Utils = { + escapeExpression: function(string) { + // don't escape SafeStrings, since they're already safe + if (string instanceof Handlebars.SafeString) { + return string.toString(); + } else if (string == null || string === false) { + return ""; + } + + if(!possible.test(string)) { return string; } + return string.replace(badChars, escapeChar); + }, + + isEmpty: function(value) { + if (typeof value === "undefined") { + return true; + } else if (value === null) { + return true; + } else if (value === false) { + return true; + } else if(Object.prototype.toString.call(value) === "[object Array]" && value.length === 0) { + return true; + } else { + return false; + } + } + }; +})();; +// lib/handlebars/compiler.js +Handlebars.Compiler = function() {}; +Handlebars.JavaScriptCompiler = function() {}; + +(function(Compiler, JavaScriptCompiler) { + Compiler.OPCODE_MAP = { + appendContent: 1, + getContext: 2, + lookupWithHelpers: 3, + lookup: 4, + append: 5, + invokeMustache: 6, + appendEscaped: 7, + pushString: 8, + truthyOrFallback: 9, + functionOrFallback: 10, + invokeProgram: 11, + invokePartial: 12, + push: 13, + invokeInverse: 14, + assignToHash: 15, + pushStringParam: 16 + }; + + Compiler.MULTI_PARAM_OPCODES = { + appendContent: 1, + getContext: 1, + lookupWithHelpers: 1, + lookup: 1, + invokeMustache: 2, + pushString: 1, + truthyOrFallback: 1, + functionOrFallback: 1, + invokeProgram: 2, + invokePartial: 1, + push: 1, + invokeInverse: 1, + assignToHash: 1, + pushStringParam: 1 + }; + + Compiler.DISASSEMBLE_MAP = {}; + + for(var prop in Compiler.OPCODE_MAP) { + var value = Compiler.OPCODE_MAP[prop]; + Compiler.DISASSEMBLE_MAP[value] = prop; + } + + Compiler.multiParamSize = function(code) { + return Compiler.MULTI_PARAM_OPCODES[Compiler.DISASSEMBLE_MAP[code]]; + }; + + Compiler.prototype = { + compiler: Compiler, + + disassemble: function() { + var opcodes = this.opcodes, opcode, nextCode; + var out = [], str, name, value; + + for(var i=0, l=opcodes.length; i 0) { + this.source[0] = this.source[0] + ", " + locals.join(", "); + } + + this.source[0] = this.source[0] + ";"; + + this.source.push("return buffer;"); + + var params = ["Handlebars", "context", "helpers", "partials"]; + + if(this.options.data) { params.push("data"); } + + for(var i=0, l=this.environment.depths.list.length; i this.stackVars.length) { this.stackVars.push("stack" + this.stackSlot); } + return "stack" + this.stackSlot; + }, + + popStack: function() { + return "stack" + this.stackSlot--; + }, + + topStack: function() { + return "stack" + this.stackSlot; + }, + + quotedString: function(str) { + return '"' + str + .replace(/\\/g, '\\\\') + .replace(/"/g, '\\"') + .replace(/\n/g, '\\n') + .replace(/\r/g, '\\r') + '"'; + } + }; + + var reservedWords = ("break case catch continue default delete do else finally " + + "for function if in instanceof new return switch this throw " + + "try typeof var void while with null true false").split(" "); + + compilerWords = JavaScriptCompiler.RESERVED_WORDS = {}; + + for(var i=0, l=reservedWords.length; i Date: Sun, 8 Jan 2012 16:27:13 -0800 Subject: [PATCH 2/4] namespace vendor assets --- Gemfile | 1 - app/assets/javascripts/locomotive.js | 2 +- app/assets/stylesheets/locomotive.css | 11 +++++------ app/assets/stylesheets/locomotive/ie.css | 7 ------- app/assets/stylesheets/locomotive/not_logged_in.css | 2 +- app/views/locomotive/shared/_head.html.haml | 3 --- .../locomotive/install/templates/locomotive.rb | 2 +- lib/locomotive/configuration.rb | 2 +- spec/dummy/config/initializers/locomotive.rb | 2 +- .../javascripts/{ => locomotive}/ICanHandlebarz.js | 0 .../{ => locomotive}/backbone.modelbinding.js | 0 .../javascripts/{ => locomotive}/backbone.sync.js | 0 .../assets/javascripts/{ => locomotive}/cookies.js | 0 .../javascripts/{ => locomotive}/datepicker_fr.js | 0 .../javascripts/{ => locomotive}/editable_field.js | 0 vendor/assets/javascripts/{ => locomotive}/growl.js | 0 .../javascripts/{ => locomotive}/handlebars.js | 0 .../javascripts/{ => locomotive}/liquid_mode.js | 0 .../javascripts/{ => locomotive}/menu_toggler.js | 0 .../assets/javascripts/{ => locomotive}/slugify.js | 0 .../javascripts/{ => locomotive}/smartupdater.js | 0 .../javascripts/{ => locomotive}/subscribe.js | 0 .../assets/javascripts/{ => locomotive}/toggle.js | 0 .../{ => locomotive}/toggle/toggle_handle-bg.png | Bin .../toggle/toggle_handle_left-bg.png | Bin .../toggle/toggle_handle_right-bg.png | Bin .../{ => locomotive}/toggle/toggle_shadow-bg.png | Bin vendor/assets/javascripts/locomotive/vendor.js | 1 + .../stylesheets/{ => locomotive}/blueprint/ie.css | 0 .../{ => locomotive}/blueprint/print.css | 0 .../{ => locomotive}/blueprint/screen.css | 0 vendor/assets/stylesheets/locomotive/jquery.css | 3 +++ .../jquery/images/ui-bg_flat_0_aaaaaa_40x100.png | Bin .../jquery/images/ui-bg_flat_75_ffffff_40x100.png | Bin .../jquery/images/ui-bg_glass_55_fbf9ee_1x400.png | Bin .../jquery/images/ui-bg_glass_65_ffffff_1x400.png | Bin .../jquery/images/ui-bg_glass_75_dadada_1x400.png | Bin .../jquery/images/ui-bg_glass_75_e6e6e6_1x400.png | Bin .../jquery/images/ui-bg_glass_95_fef1ec_1x400.png | Bin .../images/ui-bg_highlight-soft_75_cccccc_1x100.png | Bin .../jquery/images/ui-icons_222222_256x240.png | Bin .../jquery/images/ui-icons_2e83ff_256x240.png | Bin .../jquery/images/ui-icons_454545_256x240.png | Bin .../jquery/images/ui-icons_888888_256x240.png | Bin .../jquery/images/ui-icons_cd0a0a_256x240.png | Bin .../jquery/images/ui-icons_ffffff_256x240.png | Bin .../stylesheets/{ => locomotive}/jquery/ui.css | 0 .../stylesheets/{ => locomotive}/liquid_mode.css | 0 .../assets/stylesheets/{ => locomotive}/toggle.scss | 0 49 files changed, 14 insertions(+), 22 deletions(-) delete mode 100644 app/assets/stylesheets/locomotive/ie.css rename vendor/assets/javascripts/{ => locomotive}/ICanHandlebarz.js (100%) rename vendor/assets/javascripts/{ => locomotive}/backbone.modelbinding.js (100%) rename vendor/assets/javascripts/{ => locomotive}/backbone.sync.js (100%) rename vendor/assets/javascripts/{ => locomotive}/cookies.js (100%) rename vendor/assets/javascripts/{ => locomotive}/datepicker_fr.js (100%) rename vendor/assets/javascripts/{ => locomotive}/editable_field.js (100%) rename vendor/assets/javascripts/{ => locomotive}/growl.js (100%) rename vendor/assets/javascripts/{ => locomotive}/handlebars.js (100%) rename vendor/assets/javascripts/{ => locomotive}/liquid_mode.js (100%) rename vendor/assets/javascripts/{ => locomotive}/menu_toggler.js (100%) rename vendor/assets/javascripts/{ => locomotive}/slugify.js (100%) rename vendor/assets/javascripts/{ => locomotive}/smartupdater.js (100%) rename vendor/assets/javascripts/{ => locomotive}/subscribe.js (100%) rename vendor/assets/javascripts/{ => locomotive}/toggle.js (100%) rename vendor/assets/javascripts/{ => locomotive}/toggle/toggle_handle-bg.png (100%) rename vendor/assets/javascripts/{ => locomotive}/toggle/toggle_handle_left-bg.png (100%) rename vendor/assets/javascripts/{ => locomotive}/toggle/toggle_handle_right-bg.png (100%) rename vendor/assets/javascripts/{ => locomotive}/toggle/toggle_shadow-bg.png (100%) create mode 100644 vendor/assets/javascripts/locomotive/vendor.js rename vendor/assets/stylesheets/{ => locomotive}/blueprint/ie.css (100%) rename vendor/assets/stylesheets/{ => locomotive}/blueprint/print.css (100%) rename vendor/assets/stylesheets/{ => locomotive}/blueprint/screen.css (100%) create mode 100644 vendor/assets/stylesheets/locomotive/jquery.css rename vendor/assets/stylesheets/{ => locomotive}/jquery/images/ui-bg_flat_0_aaaaaa_40x100.png (100%) rename vendor/assets/stylesheets/{ => locomotive}/jquery/images/ui-bg_flat_75_ffffff_40x100.png (100%) rename vendor/assets/stylesheets/{ => locomotive}/jquery/images/ui-bg_glass_55_fbf9ee_1x400.png (100%) rename vendor/assets/stylesheets/{ => locomotive}/jquery/images/ui-bg_glass_65_ffffff_1x400.png (100%) rename vendor/assets/stylesheets/{ => locomotive}/jquery/images/ui-bg_glass_75_dadada_1x400.png (100%) rename vendor/assets/stylesheets/{ => locomotive}/jquery/images/ui-bg_glass_75_e6e6e6_1x400.png (100%) rename vendor/assets/stylesheets/{ => locomotive}/jquery/images/ui-bg_glass_95_fef1ec_1x400.png (100%) rename vendor/assets/stylesheets/{ => locomotive}/jquery/images/ui-bg_highlight-soft_75_cccccc_1x100.png (100%) rename vendor/assets/stylesheets/{ => locomotive}/jquery/images/ui-icons_222222_256x240.png (100%) rename vendor/assets/stylesheets/{ => locomotive}/jquery/images/ui-icons_2e83ff_256x240.png (100%) rename vendor/assets/stylesheets/{ => locomotive}/jquery/images/ui-icons_454545_256x240.png (100%) rename vendor/assets/stylesheets/{ => locomotive}/jquery/images/ui-icons_888888_256x240.png (100%) rename vendor/assets/stylesheets/{ => locomotive}/jquery/images/ui-icons_cd0a0a_256x240.png (100%) rename vendor/assets/stylesheets/{ => locomotive}/jquery/images/ui-icons_ffffff_256x240.png (100%) rename vendor/assets/stylesheets/{ => locomotive}/jquery/ui.css (100%) rename vendor/assets/stylesheets/{ => locomotive}/liquid_mode.css (100%) rename vendor/assets/stylesheets/{ => locomotive}/toggle.scss (100%) diff --git a/Gemfile b/Gemfile index 8b200243..720459f0 100644 --- a/Gemfile +++ b/Gemfile @@ -24,7 +24,6 @@ gem 'coffee-script', '~> 2.2.0' gem 'uglifier', '~> 1.0.4' gem 'jquery-rails', '~> 1.0.16' gem 'rails-backbone', '0.5.4' -# gem 'handlebars-rails', :git => 'git://github.com/yabawock/handlebars-rails.git' gem 'codemirror-rails' gem 'tinymce-rails' gem 'flash_cookie_session', '~> 1.1.1' diff --git a/app/assets/javascripts/locomotive.js b/app/assets/javascripts/locomotive.js index 80a27763..3e736189 100644 --- a/app/assets/javascripts/locomotive.js +++ b/app/assets/javascripts/locomotive.js @@ -16,7 +16,7 @@ //= require codemirror/modes/javascript //= require codemirror/modes/xml //= require codemirror/modes/htmlmixed -//= require_tree ../../../vendor/assets/javascripts +//= require locomotive/vendor //= require ./locomotive/application $(document).ready(function() { diff --git a/app/assets/stylesheets/locomotive.css b/app/assets/stylesheets/locomotive.css index 8c160d89..3f715097 100644 --- a/app/assets/stylesheets/locomotive.css +++ b/app/assets/stylesheets/locomotive.css @@ -3,13 +3,12 @@ * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at * the top of the compiled file, but it's generally better to create a new file per style scope. *= require_self - - *= require ../../../vendor/assets/stylesheets/blueprint/screen.css - *= require_tree ../../../vendor/assets/stylesheets/jquery + *= require locomotive/blueprint/screen.css + *= require locomotive/jquery *= require formtastic *= require codemirror - *= require codemirror/themes/default - *= require ../../../vendor/assets/stylesheets/toggle.css - *= require ../../../vendor/assets/stylesheets/liquid_mode.css + *= require codemirror/themes/default + *= require locomotive/toggle.css + *= require locomotive/liquid_mode.css *= require_tree ./locomotive */ diff --git a/app/assets/stylesheets/locomotive/ie.css b/app/assets/stylesheets/locomotive/ie.css deleted file mode 100644 index 3dfd9525..00000000 --- a/app/assets/stylesheets/locomotive/ie.css +++ /dev/null @@ -1,7 +0,0 @@ -/* - * This is a manifest file that'll automatically include all the stylesheets available in this directory - * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at - * the top of the compiled file, but it's generally better to create a new file per style scope. - *= require_self - *= require ../../../../vendor/assets/stylesheets/blueprint/ie.css -*/ diff --git a/app/assets/stylesheets/locomotive/not_logged_in.css b/app/assets/stylesheets/locomotive/not_logged_in.css index 4a7a8db3..9aa4754d 100644 --- a/app/assets/stylesheets/locomotive/not_logged_in.css +++ b/app/assets/stylesheets/locomotive/not_logged_in.css @@ -2,6 +2,6 @@ * This is a manifest file that'll automatically include all the stylesheets available in this directory * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at * the top of the compiled file, but it's generally better to create a new file per style scope. - *= require ../../../../vendor/assets/stylesheets/blueprint/screen.css + *= require locomotive/blueprint/screen.css *= require ./simple.css */ \ No newline at end of file diff --git a/app/views/locomotive/shared/_head.html.haml b/app/views/locomotive/shared/_head.html.haml index 47fa82d0..473a386f 100644 --- a/app/views/locomotive/shared/_head.html.haml +++ b/app/views/locomotive/shared/_head.html.haml @@ -10,9 +10,6 @@ = stylesheet_link_tag 'locomotive', :media => 'screen' = javascript_include_tag 'locomotive' -/ [if IE] - = stylesheet_link_tag 'locomotive/ie', :media => 'screen' - %script{ :type => 'text/javascript' } :plain window.locale = '#{I18n.locale}'; diff --git a/lib/generators/locomotive/install/templates/locomotive.rb b/lib/generators/locomotive/install/templates/locomotive.rb index c443d8a9..1445da84 100644 --- a/lib/generators/locomotive/install/templates/locomotive.rb +++ b/lib/generators/locomotive/install/templates/locomotive.rb @@ -46,7 +46,7 @@ Locomotive.configure do |config| # configure how many items we display in sub menu in the "Contents" section. # config.ui = { # :lastest_entries_nb => 5, - # :max_content_types => 1 + # :max_content_types => 4 # } # default locale (for now, only en, de, fr, pt-BR and it are supported) diff --git a/lib/locomotive/configuration.rb b/lib/locomotive/configuration.rb index f9614c20..f5dfe206 100644 --- a/lib/locomotive/configuration.rb +++ b/lib/locomotive/configuration.rb @@ -18,7 +18,7 @@ module Locomotive :manage_manage_domains => false, :ui => { :lastest_entries_nb => 5, - :max_content_types => 1 # TODO 4 + :max_content_types => 2 }, :rack_cache => { :verbose => true, diff --git a/spec/dummy/config/initializers/locomotive.rb b/spec/dummy/config/initializers/locomotive.rb index 12b82e07..7bd49141 100644 --- a/spec/dummy/config/initializers/locomotive.rb +++ b/spec/dummy/config/initializers/locomotive.rb @@ -47,7 +47,7 @@ Locomotive.configure do |config| # configure how many items we display in sub menu in the "Contents" section. # config.ui = { # :lastest_entries_nb => 5, - # :max_content_types => 1 + # :max_content_types => 4 # } # default locale (for now, only en, de, fr, pt-BR and it are supported) diff --git a/vendor/assets/javascripts/ICanHandlebarz.js b/vendor/assets/javascripts/locomotive/ICanHandlebarz.js similarity index 100% rename from vendor/assets/javascripts/ICanHandlebarz.js rename to vendor/assets/javascripts/locomotive/ICanHandlebarz.js diff --git a/vendor/assets/javascripts/backbone.modelbinding.js b/vendor/assets/javascripts/locomotive/backbone.modelbinding.js similarity index 100% rename from vendor/assets/javascripts/backbone.modelbinding.js rename to vendor/assets/javascripts/locomotive/backbone.modelbinding.js diff --git a/vendor/assets/javascripts/backbone.sync.js b/vendor/assets/javascripts/locomotive/backbone.sync.js similarity index 100% rename from vendor/assets/javascripts/backbone.sync.js rename to vendor/assets/javascripts/locomotive/backbone.sync.js diff --git a/vendor/assets/javascripts/cookies.js b/vendor/assets/javascripts/locomotive/cookies.js similarity index 100% rename from vendor/assets/javascripts/cookies.js rename to vendor/assets/javascripts/locomotive/cookies.js diff --git a/vendor/assets/javascripts/datepicker_fr.js b/vendor/assets/javascripts/locomotive/datepicker_fr.js similarity index 100% rename from vendor/assets/javascripts/datepicker_fr.js rename to vendor/assets/javascripts/locomotive/datepicker_fr.js diff --git a/vendor/assets/javascripts/editable_field.js b/vendor/assets/javascripts/locomotive/editable_field.js similarity index 100% rename from vendor/assets/javascripts/editable_field.js rename to vendor/assets/javascripts/locomotive/editable_field.js diff --git a/vendor/assets/javascripts/growl.js b/vendor/assets/javascripts/locomotive/growl.js similarity index 100% rename from vendor/assets/javascripts/growl.js rename to vendor/assets/javascripts/locomotive/growl.js diff --git a/vendor/assets/javascripts/handlebars.js b/vendor/assets/javascripts/locomotive/handlebars.js similarity index 100% rename from vendor/assets/javascripts/handlebars.js rename to vendor/assets/javascripts/locomotive/handlebars.js diff --git a/vendor/assets/javascripts/liquid_mode.js b/vendor/assets/javascripts/locomotive/liquid_mode.js similarity index 100% rename from vendor/assets/javascripts/liquid_mode.js rename to vendor/assets/javascripts/locomotive/liquid_mode.js diff --git a/vendor/assets/javascripts/menu_toggler.js b/vendor/assets/javascripts/locomotive/menu_toggler.js similarity index 100% rename from vendor/assets/javascripts/menu_toggler.js rename to vendor/assets/javascripts/locomotive/menu_toggler.js diff --git a/vendor/assets/javascripts/slugify.js b/vendor/assets/javascripts/locomotive/slugify.js similarity index 100% rename from vendor/assets/javascripts/slugify.js rename to vendor/assets/javascripts/locomotive/slugify.js diff --git a/vendor/assets/javascripts/smartupdater.js b/vendor/assets/javascripts/locomotive/smartupdater.js similarity index 100% rename from vendor/assets/javascripts/smartupdater.js rename to vendor/assets/javascripts/locomotive/smartupdater.js diff --git a/vendor/assets/javascripts/subscribe.js b/vendor/assets/javascripts/locomotive/subscribe.js similarity index 100% rename from vendor/assets/javascripts/subscribe.js rename to vendor/assets/javascripts/locomotive/subscribe.js diff --git a/vendor/assets/javascripts/toggle.js b/vendor/assets/javascripts/locomotive/toggle.js similarity index 100% rename from vendor/assets/javascripts/toggle.js rename to vendor/assets/javascripts/locomotive/toggle.js diff --git a/vendor/assets/javascripts/toggle/toggle_handle-bg.png b/vendor/assets/javascripts/locomotive/toggle/toggle_handle-bg.png similarity index 100% rename from vendor/assets/javascripts/toggle/toggle_handle-bg.png rename to vendor/assets/javascripts/locomotive/toggle/toggle_handle-bg.png diff --git a/vendor/assets/javascripts/toggle/toggle_handle_left-bg.png b/vendor/assets/javascripts/locomotive/toggle/toggle_handle_left-bg.png similarity index 100% rename from vendor/assets/javascripts/toggle/toggle_handle_left-bg.png rename to vendor/assets/javascripts/locomotive/toggle/toggle_handle_left-bg.png diff --git a/vendor/assets/javascripts/toggle/toggle_handle_right-bg.png b/vendor/assets/javascripts/locomotive/toggle/toggle_handle_right-bg.png similarity index 100% rename from vendor/assets/javascripts/toggle/toggle_handle_right-bg.png rename to vendor/assets/javascripts/locomotive/toggle/toggle_handle_right-bg.png diff --git a/vendor/assets/javascripts/toggle/toggle_shadow-bg.png b/vendor/assets/javascripts/locomotive/toggle/toggle_shadow-bg.png similarity index 100% rename from vendor/assets/javascripts/toggle/toggle_shadow-bg.png rename to vendor/assets/javascripts/locomotive/toggle/toggle_shadow-bg.png diff --git a/vendor/assets/javascripts/locomotive/vendor.js b/vendor/assets/javascripts/locomotive/vendor.js new file mode 100644 index 00000000..2becd765 --- /dev/null +++ b/vendor/assets/javascripts/locomotive/vendor.js @@ -0,0 +1 @@ +//= require_tree . \ No newline at end of file diff --git a/vendor/assets/stylesheets/blueprint/ie.css b/vendor/assets/stylesheets/locomotive/blueprint/ie.css similarity index 100% rename from vendor/assets/stylesheets/blueprint/ie.css rename to vendor/assets/stylesheets/locomotive/blueprint/ie.css diff --git a/vendor/assets/stylesheets/blueprint/print.css b/vendor/assets/stylesheets/locomotive/blueprint/print.css similarity index 100% rename from vendor/assets/stylesheets/blueprint/print.css rename to vendor/assets/stylesheets/locomotive/blueprint/print.css diff --git a/vendor/assets/stylesheets/blueprint/screen.css b/vendor/assets/stylesheets/locomotive/blueprint/screen.css similarity index 100% rename from vendor/assets/stylesheets/blueprint/screen.css rename to vendor/assets/stylesheets/locomotive/blueprint/screen.css diff --git a/vendor/assets/stylesheets/locomotive/jquery.css b/vendor/assets/stylesheets/locomotive/jquery.css new file mode 100644 index 00000000..aae875e5 --- /dev/null +++ b/vendor/assets/stylesheets/locomotive/jquery.css @@ -0,0 +1,3 @@ +/* + *= require_tree ./jquery +*/ \ No newline at end of file diff --git a/vendor/assets/stylesheets/jquery/images/ui-bg_flat_0_aaaaaa_40x100.png b/vendor/assets/stylesheets/locomotive/jquery/images/ui-bg_flat_0_aaaaaa_40x100.png similarity index 100% rename from vendor/assets/stylesheets/jquery/images/ui-bg_flat_0_aaaaaa_40x100.png rename to vendor/assets/stylesheets/locomotive/jquery/images/ui-bg_flat_0_aaaaaa_40x100.png diff --git a/vendor/assets/stylesheets/jquery/images/ui-bg_flat_75_ffffff_40x100.png b/vendor/assets/stylesheets/locomotive/jquery/images/ui-bg_flat_75_ffffff_40x100.png similarity index 100% rename from vendor/assets/stylesheets/jquery/images/ui-bg_flat_75_ffffff_40x100.png rename to vendor/assets/stylesheets/locomotive/jquery/images/ui-bg_flat_75_ffffff_40x100.png diff --git a/vendor/assets/stylesheets/jquery/images/ui-bg_glass_55_fbf9ee_1x400.png b/vendor/assets/stylesheets/locomotive/jquery/images/ui-bg_glass_55_fbf9ee_1x400.png similarity index 100% rename from vendor/assets/stylesheets/jquery/images/ui-bg_glass_55_fbf9ee_1x400.png rename to vendor/assets/stylesheets/locomotive/jquery/images/ui-bg_glass_55_fbf9ee_1x400.png diff --git a/vendor/assets/stylesheets/jquery/images/ui-bg_glass_65_ffffff_1x400.png b/vendor/assets/stylesheets/locomotive/jquery/images/ui-bg_glass_65_ffffff_1x400.png similarity index 100% rename from vendor/assets/stylesheets/jquery/images/ui-bg_glass_65_ffffff_1x400.png rename to vendor/assets/stylesheets/locomotive/jquery/images/ui-bg_glass_65_ffffff_1x400.png diff --git a/vendor/assets/stylesheets/jquery/images/ui-bg_glass_75_dadada_1x400.png b/vendor/assets/stylesheets/locomotive/jquery/images/ui-bg_glass_75_dadada_1x400.png similarity index 100% rename from vendor/assets/stylesheets/jquery/images/ui-bg_glass_75_dadada_1x400.png rename to vendor/assets/stylesheets/locomotive/jquery/images/ui-bg_glass_75_dadada_1x400.png diff --git a/vendor/assets/stylesheets/jquery/images/ui-bg_glass_75_e6e6e6_1x400.png b/vendor/assets/stylesheets/locomotive/jquery/images/ui-bg_glass_75_e6e6e6_1x400.png similarity index 100% rename from vendor/assets/stylesheets/jquery/images/ui-bg_glass_75_e6e6e6_1x400.png rename to vendor/assets/stylesheets/locomotive/jquery/images/ui-bg_glass_75_e6e6e6_1x400.png diff --git a/vendor/assets/stylesheets/jquery/images/ui-bg_glass_95_fef1ec_1x400.png b/vendor/assets/stylesheets/locomotive/jquery/images/ui-bg_glass_95_fef1ec_1x400.png similarity index 100% rename from vendor/assets/stylesheets/jquery/images/ui-bg_glass_95_fef1ec_1x400.png rename to vendor/assets/stylesheets/locomotive/jquery/images/ui-bg_glass_95_fef1ec_1x400.png diff --git a/vendor/assets/stylesheets/jquery/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/vendor/assets/stylesheets/locomotive/jquery/images/ui-bg_highlight-soft_75_cccccc_1x100.png similarity index 100% rename from vendor/assets/stylesheets/jquery/images/ui-bg_highlight-soft_75_cccccc_1x100.png rename to vendor/assets/stylesheets/locomotive/jquery/images/ui-bg_highlight-soft_75_cccccc_1x100.png diff --git a/vendor/assets/stylesheets/jquery/images/ui-icons_222222_256x240.png b/vendor/assets/stylesheets/locomotive/jquery/images/ui-icons_222222_256x240.png similarity index 100% rename from vendor/assets/stylesheets/jquery/images/ui-icons_222222_256x240.png rename to vendor/assets/stylesheets/locomotive/jquery/images/ui-icons_222222_256x240.png diff --git a/vendor/assets/stylesheets/jquery/images/ui-icons_2e83ff_256x240.png b/vendor/assets/stylesheets/locomotive/jquery/images/ui-icons_2e83ff_256x240.png similarity index 100% rename from vendor/assets/stylesheets/jquery/images/ui-icons_2e83ff_256x240.png rename to vendor/assets/stylesheets/locomotive/jquery/images/ui-icons_2e83ff_256x240.png diff --git a/vendor/assets/stylesheets/jquery/images/ui-icons_454545_256x240.png b/vendor/assets/stylesheets/locomotive/jquery/images/ui-icons_454545_256x240.png similarity index 100% rename from vendor/assets/stylesheets/jquery/images/ui-icons_454545_256x240.png rename to vendor/assets/stylesheets/locomotive/jquery/images/ui-icons_454545_256x240.png diff --git a/vendor/assets/stylesheets/jquery/images/ui-icons_888888_256x240.png b/vendor/assets/stylesheets/locomotive/jquery/images/ui-icons_888888_256x240.png similarity index 100% rename from vendor/assets/stylesheets/jquery/images/ui-icons_888888_256x240.png rename to vendor/assets/stylesheets/locomotive/jquery/images/ui-icons_888888_256x240.png diff --git a/vendor/assets/stylesheets/jquery/images/ui-icons_cd0a0a_256x240.png b/vendor/assets/stylesheets/locomotive/jquery/images/ui-icons_cd0a0a_256x240.png similarity index 100% rename from vendor/assets/stylesheets/jquery/images/ui-icons_cd0a0a_256x240.png rename to vendor/assets/stylesheets/locomotive/jquery/images/ui-icons_cd0a0a_256x240.png diff --git a/vendor/assets/stylesheets/jquery/images/ui-icons_ffffff_256x240.png b/vendor/assets/stylesheets/locomotive/jquery/images/ui-icons_ffffff_256x240.png similarity index 100% rename from vendor/assets/stylesheets/jquery/images/ui-icons_ffffff_256x240.png rename to vendor/assets/stylesheets/locomotive/jquery/images/ui-icons_ffffff_256x240.png diff --git a/vendor/assets/stylesheets/jquery/ui.css b/vendor/assets/stylesheets/locomotive/jquery/ui.css similarity index 100% rename from vendor/assets/stylesheets/jquery/ui.css rename to vendor/assets/stylesheets/locomotive/jquery/ui.css diff --git a/vendor/assets/stylesheets/liquid_mode.css b/vendor/assets/stylesheets/locomotive/liquid_mode.css similarity index 100% rename from vendor/assets/stylesheets/liquid_mode.css rename to vendor/assets/stylesheets/locomotive/liquid_mode.css diff --git a/vendor/assets/stylesheets/toggle.scss b/vendor/assets/stylesheets/locomotive/toggle.scss similarity index 100% rename from vendor/assets/stylesheets/toggle.scss rename to vendor/assets/stylesheets/locomotive/toggle.scss From 4c204ef6a6de2951e5f108132a47fdd494045699 Mon Sep 17 00:00:00 2001 From: did Date: Mon, 9 Jan 2012 06:49:59 -0800 Subject: [PATCH 3/4] refactor and clean code (wip) + the api controller has been deleted and replace by the entry_submission_controller (+ custom responder) --- Gemfile | 10 +- Gemfile.lock | 43 ++--- README.textile | 2 +- .../locomotive/application.js.coffee | 2 - .../locomotive/models/custom_field.js.coffee | 2 +- .../javascripts/locomotive/routers/.gitkeep | 0 .../views/content_types/_form_view.js.coffee | 10 +- .../locomotive/api_contents_controller.rb | 61 ------- app/controllers/locomotive/base_controller.rb | 62 +------ .../locomotive/public/base_controller.rb | 19 +++ .../public/content_entries_controller.rb | 50 ++++++ .../locomotive/public/rendering_controller.rb | 26 +++ .../locomotive/public/robots_controller.rb | 16 ++ .../locomotive/public/sitemaps_controller.rb | 14 ++ .../locomotive/rendering_controller.rb | 22 --- .../locomotive/robots_controller.rb | 18 -- .../locomotive/sitemaps_controller.rb | 18 -- app/mailers/locomotive/notifications.rb | 4 +- app/models/locomotive/content_entry.rb | 8 +- app/models/locomotive/content_type.rb | 143 ++++++++-------- app/presenters/locomotive/base_presenter.rb | 8 +- .../locomotive/content_entry_presenter.rb | 58 +++++-- .../locomotive/content_types/_form.html.haml | 4 +- .../locomotive/content_types/edit.html.haml | 4 +- .../custom_fields/_custom_form.html.haml | 10 -- .../locomotive/custom_fields/_form.html.haml | 2 +- .../custom_fields/types/_boolean.html.haml | 5 +- .../custom_fields/types/_category.html.haml | 4 - .../custom_fields/types/_date.html.haml | 6 +- .../custom_fields/types/_file.html.haml | 5 +- .../custom_fields/types/_select.html.haml | 6 +- .../custom_fields/types/_string.html.haml | 5 +- .../custom_fields/types/_text.html.haml | 6 +- .../notifications/new_content_entry.html.haml | 13 +- .../{ => public}/sitemaps/show.xml.builder | 0 config/locales/admin_ui.en.yml | 5 +- config/locales/formtastic.en.yml | 7 +- config/routes.rb | 15 +- doc/TODO | 10 +- doc/changelogs/version_2.txt | 7 +- lib/locomotive.rb | 13 +- lib/locomotive/action_controller.rb | 3 + lib/locomotive/action_controller/helpers.rb | 66 ++++++++ .../action_controller/public_responder.rb | 17 ++ lib/locomotive/action_controller/responder.rb | 63 +++++++ lib/locomotive/engine.rb | 2 +- lib/locomotive/liquid/drops/content_types.rb | 79 +++++++++ lib/locomotive/liquid/drops/contents.rb | 158 +++++++++--------- lib/locomotive/render.rb | 11 +- lib/locomotive/responder.rb | 61 ------- locomotive_cms.gemspec | 2 +- 51 files changed, 677 insertions(+), 508 deletions(-) delete mode 100644 app/assets/javascripts/locomotive/routers/.gitkeep delete mode 100644 app/controllers/locomotive/api_contents_controller.rb create mode 100644 app/controllers/locomotive/public/base_controller.rb create mode 100644 app/controllers/locomotive/public/content_entries_controller.rb create mode 100644 app/controllers/locomotive/public/rendering_controller.rb create mode 100644 app/controllers/locomotive/public/robots_controller.rb create mode 100644 app/controllers/locomotive/public/sitemaps_controller.rb delete mode 100644 app/controllers/locomotive/rendering_controller.rb delete mode 100644 app/controllers/locomotive/robots_controller.rb delete mode 100644 app/controllers/locomotive/sitemaps_controller.rb delete mode 100644 app/views/locomotive/custom_fields/_custom_form.html.haml delete mode 100644 app/views/locomotive/custom_fields/types/_category.html.haml rename app/views/locomotive/{ => public}/sitemaps/show.xml.builder (100%) create mode 100644 lib/locomotive/action_controller.rb create mode 100644 lib/locomotive/action_controller/helpers.rb create mode 100644 lib/locomotive/action_controller/public_responder.rb create mode 100644 lib/locomotive/action_controller/responder.rb create mode 100644 lib/locomotive/liquid/drops/content_types.rb delete mode 100644 lib/locomotive/responder.rb diff --git a/Gemfile b/Gemfile index 720459f0..159b799f 100644 --- a/Gemfile +++ b/Gemfile @@ -6,22 +6,22 @@ gem 'rake', '0.9.2' gem 'rails', '~> 3.1.3' -gem 'devise', :git => 'git://github.com/plataformatec/devise.git'# FIXME: waiting for the new devise gem coming soon +gem 'devise', '~> 1.5.3' gem 'cancan', '~> 1.6.7' -gem 'bson_ext', '~> 1.4.0' -gem 'mongoid', '~> 2.3.3' +gem 'mongo', '~> 1.5.2' +gem 'bson_ext', '~> 1.5.2' +gem 'mongoid', '~> 2.4.0' gem 'locomotive_mongoid_acts_as_tree', :git => 'git@github.com:locomotivecms/mongoid_acts_as_tree.git' -# gem 'custom_fields', :git => 'git://github.com/locomotivecms/custom_fields.git' gem 'custom_fields', :path => '../gems/custom_fields' # DEV # gem 'custom_fields', :git => 'git://github.com/locomotivecms/custom_fields.git', :branch => 'experimental' gem 'kaminari' gem 'haml', '~> 3.1.3' gem 'sass-rails', '~> 3.1.4' -gem "compass", :git => 'git://github.com/chriseppstein/compass.git' gem 'coffee-script', '~> 2.2.0' gem 'uglifier', '~> 1.0.4' +gem 'compass', '~> 0.12.alpha.4' gem 'jquery-rails', '~> 1.0.16' gem 'rails-backbone', '0.5.4' gem 'codemirror-rails' diff --git a/Gemfile.lock b/Gemfile.lock index e36053b2..d67fec61 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,22 +1,3 @@ -GIT - remote: git://github.com/chriseppstein/compass.git - revision: bffba483754cb9381fa51efd8e2a1f0482a21ac6 - specs: - compass (0.12.alpha.4.bffba48) - chunky_png (~> 1.2) - fssm (>= 0.2.7) - sass (~> 3.1) - -GIT - remote: git://github.com/plataformatec/devise.git - revision: a949f9eca24f9d43f516363fbf2f5d004623355e - specs: - devise (2.0.0.rc) - bcrypt-ruby (~> 3.0) - orm_adapter (~> 0.0.3) - railties (~> 3.1) - warden (~> 1.1) - GIT remote: git@github.com:locomotivecms/mongoid_acts_as_tree.git revision: ca494d22c3d7946385aba1153c017d9c30e9f9d3 @@ -29,7 +10,7 @@ PATH custom_fields (2.0.0.rc1) activesupport (~> 3.1.3) carrierwave-mongoid (~> 0.1.3) - mongoid (~> 2.3.4) + mongoid (~> 2.4.0) GEM remote: http://rubygems.org/ @@ -73,7 +54,8 @@ GEM ZenTest (>= 4.4.1) bcrypt-ruby (3.0.1) bson (1.5.2) - bson_ext (1.4.0) + bson_ext (1.5.2) + bson (= 1.5.2) builder (3.0.0) bushido (0.0.35) highline (>= 1.6.1) @@ -105,6 +87,10 @@ GEM coffee-script-source execjs coffee-script-source (1.2.0) + compass (0.12.alpha.4) + chunky_png (~> 1.2) + fssm (>= 0.2.7) + sass (~> 3.1) cucumber (1.1.4) builder (>= 2.1.2) diff-lcs (>= 1.1.2) @@ -121,6 +107,10 @@ GEM delayed_job_mongoid (1.0.8) delayed_job (~> 3.0.0) mongoid (>= 2.0) + devise (1.5.3) + bcrypt-ruby (~> 3.0) + orm_adapter (~> 0.0.3) + warden (~> 1.1) diff-lcs (1.1.3) dragonfly (0.9.9) rack @@ -182,7 +172,7 @@ GEM mocha (0.9.12) mongo (1.5.2) bson (= 1.5.2) - mongoid (2.3.4) + mongoid (2.4.0) activemodel (~> 3.1) mongo (~> 1.3) tzinfo (~> 0.3.22) @@ -298,7 +288,7 @@ DEPENDENCIES ZenTest actionmailer-with-request (~> 0.3.0) autotest - bson_ext (~> 1.4.0) + bson_ext (~> 1.5.2) bushido (= 0.0.35) cancan (~> 1.6.7) capybara @@ -306,12 +296,12 @@ DEPENDENCIES cells (~> 3.7.0) codemirror-rails coffee-script (~> 2.2.0) - compass! + compass (~> 0.12.alpha.4) cucumber-rails custom_fields! database_cleaner delayed_job_mongoid (~> 1.0.8) - devise! + devise (~> 1.5.3) dragonfly (~> 0.9.8) factory_girl_rails (~> 1.1) flash_cookie_session (~> 1.1.1) @@ -328,7 +318,8 @@ DEPENDENCIES locomotive_mongoid_acts_as_tree! mimetype-fu (~> 0.1.2) mocha (= 0.9.12) - mongoid (~> 2.3.3) + mongo (~> 1.5.2) + mongoid (~> 2.4.0) pickle rack-cache (~> 1.1) rails (~> 3.1.3) diff --git a/README.textile b/README.textile index 17e0dda5..26afbd32 100644 --- a/README.textile +++ b/README.textile @@ -48,7 +48,7 @@ h2. Community h2. Team * Developers: "Didier Lafforgue":http://www.nocoffee.fr, "Jacques Crocker":http://www.railsjedi.com, "Mario Visic":http://www.mariovisic.com -* Contributors: "Dirk Kelly":http://www.dirkkelly.com, "Raphael Costa":http://raphaelcosta.net (Brazilian Portuguese translation), "Bernd Hauser":http://www.designhunger.de (German translation), "Andrea Frigido":http://www.frisoft.it (Italian translation), "Enrique García":https://github.com/kikito (Spanish translation), "Lars Smit":https://github.com/larssmit (Dutch translation), "PitOn":https://github.com/GarPit (Russian translation) +* Contributors: "Dirk Kelly":http://www.dirkkelly.com, "Raphael Costa":http://raphaelcosta.net (Brazilian Portuguese translation), "Bernd Hauser":http://www.designhunger.de (German translation), "Andrea Frigido":http://www.frisoft.it (Italian translation), "Enrique García":https://github.com/kikito (Spanish translation), "Lars Smit":https://github.com/larssmit (Dutch translation), "PitOn":https://github.com/GarPit (Russian translation), "paulsponagl":https://github.com/paulsponagl * UI Designer: "Sacha Greif":http://www.sachagreif.com * IE maintainer: "Alex Sanford":https://github.com/alexsanford diff --git a/app/assets/javascripts/locomotive/application.js.coffee b/app/assets/javascripts/locomotive/application.js.coffee index 2c53832a..57bdc3fd 100644 --- a/app/assets/javascripts/locomotive/application.js.coffee +++ b/app/assets/javascripts/locomotive/application.js.coffee @@ -3,13 +3,11 @@ #= require_tree ./utils #= require_tree ./models #= require_tree ./views -#= require_tree ./routers window.Locomotive = mount_on: '/locomotive' Models: {} Collections: {} - Routers: {} Views: {} window.Locomotive.Views.Memberships = {} \ No newline at end of file diff --git a/app/assets/javascripts/locomotive/models/custom_field.js.coffee b/app/assets/javascripts/locomotive/models/custom_field.js.coffee index ffa8f96c..d0a6031e 100644 --- a/app/assets/javascripts/locomotive/models/custom_field.js.coffee +++ b/app/assets/javascripts/locomotive/models/custom_field.js.coffee @@ -13,7 +13,7 @@ class Locomotive.Models.CustomField extends Backbone.Model toJSONForSave: -> _.tap {}, (hash) => for key, value of @.toJSON() - hash[key] = value unless _.include(['select_options', 'type_text', 'created_at', 'updated_at'], key) + hash[key] = value unless _.include(['select_options', 'type_text', 'text_formatting_text', 'created_at', 'updated_at'], key) hash.select_options_attributes = @get('select_options').toJSONForSave() if @get('select_options') class Locomotive.Models.CustomFieldsCollection extends Backbone.Collection diff --git a/app/assets/javascripts/locomotive/routers/.gitkeep b/app/assets/javascripts/locomotive/routers/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/app/assets/javascripts/locomotive/views/content_types/_form_view.js.coffee b/app/assets/javascripts/locomotive/views/content_types/_form_view.js.coffee index 3f2f481a..9ec68e18 100644 --- a/app/assets/javascripts/locomotive/views/content_types/_form_view.js.coffee +++ b/app/assets/javascripts/locomotive/views/content_types/_form_view.js.coffee @@ -23,7 +23,7 @@ class Locomotive.Views.ContentTypes.FormView extends Locomotive.Views.Shared.For @enable_liquid_editing() # turn textarea into editable liquid code zone - @enable_public_form_checkbox() + @enable_public_submission_checkbox() @enable_order_by_toggler() @@ -48,10 +48,10 @@ class Locomotive.Views.ContentTypes.FormView extends Locomotive.Views.Shared.For theme: 'default medium' onChange: (editor) => @model.set(raw_item_template: editor.getValue()) - enable_public_form_checkbox: -> - @_enable_checkbox 'public_form_enabled', - on_callback: => @$('#content_type_public_form_accounts_input').show() - off_callback: => @$('#content_type_public_form_accounts_input').hide() + enable_public_submission_checkbox: -> + @_enable_checkbox 'public_submission_enabled', + on_callback: => @$('#content_type_public_submission_accounts_input').show() + off_callback: => @$('#content_type_public_submission_accounts_input').hide() enable_order_by_toggler: -> @$('#content_type_order_by_input').bind 'change', (event) => diff --git a/app/controllers/locomotive/api_contents_controller.rb b/app/controllers/locomotive/api_contents_controller.rb deleted file mode 100644 index d5a06833..00000000 --- a/app/controllers/locomotive/api_contents_controller.rb +++ /dev/null @@ -1,61 +0,0 @@ -module Locomotive - class ApiContentsController < ActionController::Base - - # FIXME: NEED REFACTORING - - include Locomotive::Routing::SiteDispatcher - - before_filter :require_site - - before_filter :set_content_type - - before_filter :block_content_type_with_disabled_api - - before_filter :sanitize_content_params, :only => :create - - def create - @entry = @content_type.entries.build(params[:entry]) - - respond_to do |format| - if @entry.save - format.json { render :json => { :entry => @entry } } - format.html do - flash[@content_type.slug.singularize] = @entry.aliased_attributes - redirect_to params[:success_callback] - end - else - format.json { render :json => { :entry => @content, :errors => @content.errors } } - format.html do - flash[@content_type.slug.singularize] = @content.aliased_attributes - flash['errors'] = @content.errors_to_hash - redirect_to params[:error_callback] - end - end - end - end - - protected - - def set_content_type - @content_type = current_site.content_types.where(:slug => params[:slug]).first - end - - def block_content_type_with_disabled_api - unless @content_type.api_enabled? - respond_to do |format| - format.json { render :json => { :error => 'Api not enabled' }, :status => :forbidden } - format.html { render :text => 'Api not enabled', :status => :forbidden } - end - return false - end - end - - def sanitize_content_params - (params[:content] || {}).each do |key, value| - next unless value.is_a?(String) - params[:content][key] = Sanitize.clean(value, Sanitize::Config::BASIC) - end - end - - end -end diff --git a/app/controllers/locomotive/base_controller.rb b/app/controllers/locomotive/base_controller.rb index e62f9ff5..17e1aeab 100644 --- a/app/controllers/locomotive/base_controller.rb +++ b/app/controllers/locomotive/base_controller.rb @@ -3,6 +3,8 @@ module Locomotive include Locomotive::Routing::SiteDispatcher + include Locomotive::ActionController::Helpers + layout '/locomotive/layouts/application' before_filter :require_account @@ -17,15 +19,11 @@ module Locomotive before_filter :set_current_thread_variables - helper_method :sections, :current_site_public_url, :switch_to_site_url, :public_page_url, :current_ability + helper_method :sections, :current_ability - # https://rails.lighthouseapp.com/projects/8994/tickets/1905-apphelpers-within-plugin-not-being-mixed-in - helper Locomotive::BaseHelper, Locomotive::ContentTypesHelper #, Locomotive::BoxHelper - # Dir[File.dirname(__FILE__) + "/../../helpers/**/*_helper.rb"].each do |file| - # helper "locomotive/#{File.basename(file, '.rb').gsub(/_helper$/, '')}" - # end + helper Locomotive::BaseHelper, Locomotive::ContentTypesHelper - self.responder = Locomotive::Responder # custom responder + self.responder = Locomotive::ActionController::Responder # custom responder respond_to :html @@ -44,8 +42,8 @@ module Locomotive protected def set_current_thread_variables - Thread.current[:account] = current_locomotive_account - Thread.current[:site] = current_site + Thread.current[:account] = current_locomotive_account + Thread.current[:site] = current_site end def current_ability @@ -56,51 +54,5 @@ module Locomotive authenticate_locomotive_account! end - def self.sections(main, sub = nil) - before_filter do |c| - sub = sub.call(c) if sub.respond_to?(:call) - sections = { :main => main, :sub => sub } - c.instance_variable_set(:@locomotive_sections, sections) - end - end - - def sections(key = nil) - if !key.nil? && key.to_sym == :sub - @locomotive_sections[:sub] || self.controller_name.dasherize - else - @locomotive_sections[:main] - end - end - - def set_locale - I18n.locale = current_locomotive_account.locale rescue Locomotive.config.default_locale - end - - # ___ site/page urls builder ___ - - def current_site_public_url - request.protocol + request.host_with_port - end - - def switch_to_site_url(site, options = {}) - options = { :fullpath => true, :protocol => true }.merge(options) - - url = "#{site.subdomain}.#{Locomotive.config.domain}" - url += ":#{request.port}" if request.port != 80 - - url = File.join(url, request.fullpath) if options[:fullpath] - url = "http://#{url}" if options[:protocol] - url - end - - def public_page_url(page, options = {}) - if content = options.delete(:content) - File.join(current_site_public_url, page.fullpath.gsub('content_type_template', ''), content._slug) - else - File.join(current_site_public_url, page.fullpath) - end - end - - end end diff --git a/app/controllers/locomotive/public/base_controller.rb b/app/controllers/locomotive/public/base_controller.rb new file mode 100644 index 00000000..8539cab1 --- /dev/null +++ b/app/controllers/locomotive/public/base_controller.rb @@ -0,0 +1,19 @@ +module Locomotive + module Public + class BaseController < ApplicationController + + include Locomotive::Routing::SiteDispatcher + + include Locomotive::ActionController::Helpers + + before_filter :require_site + + protected + + def set_locale + logger.info "[public/set_locale] TODO" + end + + end + end +end \ No newline at end of file diff --git a/app/controllers/locomotive/public/content_entries_controller.rb b/app/controllers/locomotive/public/content_entries_controller.rb new file mode 100644 index 00000000..e4a0c418 --- /dev/null +++ b/app/controllers/locomotive/public/content_entries_controller.rb @@ -0,0 +1,50 @@ +module Locomotive + module Public + class ContentEntriesController < BaseController + + before_filter :set_content_type + + before_filter :sanitize_entry_params, :only => :create + + skip_before_filter :verify_authenticity_token + + self.responder = Locomotive::ActionController::PublicResponder # custom responder + + respond_to :html, :json + + def create + @entry = @content_type.entries.create(params[:entry]) + flash[@content_type.slug.singularize] = @entry.to_presenter(:include_errors => true).as_json + respond_with @entry, :location => self.callback_url + end + + protected + + def set_content_type + @content_type = current_site.content_types.where(:slug => params[:slug]).first + + # check if ability to receive public submissions + unless @content_type.public_submission_enabled? + respond_to do |format| + format.json { render :json => { :error => 'Public submissions not accepted' }, :status => :forbidden } + format.html { render :text => 'Public submissions not accepted', :status => :forbidden } + end + return false + end + end + + def callback_url + @entry.errors.empty? ? params[:success_callback] : params[:error_callback] + end + + def sanitize_entry_params + entry_params = params[:entry] || params[:content] || {} + entry_params.each do |key, value| + next unless value.is_a?(String) + entry_params[key] = Sanitize.clean(value, Sanitize::Config::BASIC) + end + end + + end + end +end diff --git a/app/controllers/locomotive/public/rendering_controller.rb b/app/controllers/locomotive/public/rendering_controller.rb new file mode 100644 index 00000000..705355ff --- /dev/null +++ b/app/controllers/locomotive/public/rendering_controller.rb @@ -0,0 +1,26 @@ +module Locomotive + module Public + class RenderingController < ApplicationController + + include Locomotive::Routing::SiteDispatcher + + include Locomotive::Render + + before_filter :require_site + + before_filter :authenticate_admin!, :only => [:edit] + + before_filter :validate_site_membership, :only => [:edit] + + def show + render_locomotive_page + end + + def edit + @editing = true + render_locomotive_page + end + + end + end +end \ No newline at end of file diff --git a/app/controllers/locomotive/public/robots_controller.rb b/app/controllers/locomotive/public/robots_controller.rb new file mode 100644 index 00000000..71e65106 --- /dev/null +++ b/app/controllers/locomotive/public/robots_controller.rb @@ -0,0 +1,16 @@ +module Locomotive + module Public + class RobotsController < BaseController + + include Locomotive::Render + + respond_to :txt + + def show + template = ::Liquid::Template.parse(current_site.robots_txt) + render :text => template.render('request_host' => self.request.host.downcase) + end + + end + end +end \ No newline at end of file diff --git a/app/controllers/locomotive/public/sitemaps_controller.rb b/app/controllers/locomotive/public/sitemaps_controller.rb new file mode 100644 index 00000000..717aff61 --- /dev/null +++ b/app/controllers/locomotive/public/sitemaps_controller.rb @@ -0,0 +1,14 @@ +module Locomotive + module Public + class SitemapsController < BaseController + + respond_to :xml + + def show + @pages = current_site.pages.published + respond_with @pages + end + + end + end +end \ No newline at end of file diff --git a/app/controllers/locomotive/rendering_controller.rb b/app/controllers/locomotive/rendering_controller.rb deleted file mode 100644 index cfd7bc00..00000000 --- a/app/controllers/locomotive/rendering_controller.rb +++ /dev/null @@ -1,22 +0,0 @@ -module Locomotive - class RenderingController < ActionController::Base - - include Locomotive::Routing::SiteDispatcher - - include Locomotive::Render - - before_filter :require_site - before_filter :authenticate_admin!, :only => [:edit] - before_filter :validate_site_membership, :only => [:edit] - - def show - render_locomotive_page - end - - def edit - @editing = true - render_locomotive_page - end - - end -end diff --git a/app/controllers/locomotive/robots_controller.rb b/app/controllers/locomotive/robots_controller.rb deleted file mode 100644 index 741693aa..00000000 --- a/app/controllers/locomotive/robots_controller.rb +++ /dev/null @@ -1,18 +0,0 @@ -module Locomotive - class RobotsController < ActionController::Base - - include Locomotive::Routing::SiteDispatcher - - include Locomotive::Render - - before_filter :require_site - - respond_to :txt - - def show - template = ::Liquid::Template.parse(current_site.robots_txt) - render :text => template.render('request_host' => self.request.host.downcase) - end - - end -end \ No newline at end of file diff --git a/app/controllers/locomotive/sitemaps_controller.rb b/app/controllers/locomotive/sitemaps_controller.rb deleted file mode 100644 index 79ffc48f..00000000 --- a/app/controllers/locomotive/sitemaps_controller.rb +++ /dev/null @@ -1,18 +0,0 @@ -module Locomotive - class SitemapsController < BaseController - - skip_before_filter :require_account, :validate_site_membership, :set_locale - - before_filter :require_site - - respond_to :xml - - skip_load_and_authorize_resource - - def show - @pages = current_site.pages.published - respond_with @pages - end - - end -end diff --git a/app/mailers/locomotive/notifications.rb b/app/mailers/locomotive/notifications.rb index c7b24ae0..b59e1364 100644 --- a/app/mailers/locomotive/notifications.rb +++ b/app/mailers/locomotive/notifications.rb @@ -4,9 +4,9 @@ module Locomotive default :from => Locomotive.config.mailer_sender def new_content_entry(account, entry) - @account, @entry = account, entry + @account, @entry, @type = account, entry.to_presenter, entry.content_type - subject = t('locomotive.notifications.new_content_entry.subject', :type => entry.content_type.name, :locale => account.locale) + subject = t('locomotive.notifications.new_content_entry.subject', :type => @type.name, :locale => account.locale) mail :subject => subject, :to => account.email end diff --git a/app/models/locomotive/content_entry.rb b/app/models/locomotive/content_entry.rb index c5f710d3..8fa6aaed 100644 --- a/app/models/locomotive/content_entry.rb +++ b/app/models/locomotive/content_entry.rb @@ -64,8 +64,8 @@ module Locomotive Locomotive::Liquid::Drops::ContentEntry.new(self) end - def to_presenter - Locomotive::ContentEntryPresenter.new(self) + def to_presenter(options = {}) + Locomotive::ContentEntryPresenter.new(self, options) end def as_json(options = {}) @@ -119,10 +119,10 @@ module Locomotive end def send_notifications - return if !self.content_type.public_form_enabled? || self.content_type.public_form_accounts.blank? + return if !self.content_type.public_submission_enabled? || self.content_type.public_submission_accounts.blank? self.content_type.site.accounts.each do |account| - next unless self.content_type.public_form_accounts.include?(account._id.to_s) + next unless self.content_type.public_submission_accounts.include?(account._id.to_s) Locomotive::Notifications.new_content_entry(account, self).deliver end diff --git a/app/models/locomotive/content_type.rb b/app/models/locomotive/content_type.rb index 35436344..43f7c756 100644 --- a/app/models/locomotive/content_type.rb +++ b/app/models/locomotive/content_type.rb @@ -11,13 +11,13 @@ module Locomotive field :name field :description field :slug - field :label_field_id, :type => BSON::ObjectId + field :label_field_id, :type => BSON::ObjectId field :label_field_name - field :group_by_field_id, :type => BSON::ObjectId + field :group_by_field_id, :type => BSON::ObjectId field :order_by - field :order_direction, :default => 'asc' - field :public_form_enabled, :type => Boolean, :default => false - field :public_form_accounts, :type => Array + field :order_direction, :default => 'asc' + field :public_submission_enabled, :type => Boolean, :default => false + field :public_submission_accounts, :type => Array ## associations ## belongs_to :site, :class_name => 'Locomotive::Site' @@ -53,8 +53,8 @@ module Locomotive [order_by_attribute, direction] end - def ordered_entries - self.entries.order_by([order_by_definition]) + def ordered_entries(conditions = {}) + self.entries.order_by([order_by_definition]).where(conditions) end def groupable? @@ -81,71 +81,6 @@ module Locomotive self.to_presenter.as_json end - # def list_or_group_contents - # if self.groupable? - # groups = self.contents.klass.send(:"group_by_#{self.group_by_field._alias}", :ordered_contents) - # - # # look for items with no category or unknown ones - # items_without_category = self.contents.find_all { |c| !self.group_by_field.category_ids.include?(c.send(self.group_by_field_name)) } - # if not items_without_category.empty? - # groups << { :name => nil, :items => items_without_category } - # else - # groups - # end - # else - # self.ordered_contents - # end - # end - # - # def latest_updated_contents - # self.contents.latest_updated.reject { |c| !c.persisted? } - # end - # - # def ordered_contents(conditions = {}) - # column = self.order_by.to_sym - # - # list = (if conditions.nil? || conditions.empty? - # self.contents - # else - # conditions_with_names = {} - # - # conditions.each do |key, value| - # # convert alias (key) to name - # field = self.entries_custom_fields.detect { |f| f._alias == key } - # - # case field.kind.to_sym - # when :category - # if (category_item = field.category_items.where(:name => value).first).present? - # conditions_with_names[field._name.to_sym] = category_item._id - # end - # else - # conditions_with_names[field._name.to_sym] = value - # end - # end - # - # self.contents.where(conditions_with_names) - # end).sort { |a, b| (a.send(column) && b.send(column)) ? (a.send(column) || 0) <=> (b.send(column) || 0) : 0 } - # - # return list if self.order_manually? - # - # self.asc_order? ? list : list.reverse - # end - # - # def sort_contents!(ids) - # ids.each_with_index do |id, position| - # self.contents.find(BSON::ObjectId(id))._position_in_list = position - # end - # self.save - # end - # - # def highlighted_field - # self.entries_custom_fields.detect { |f| f._name == self.highlighted_field_name } - # end - # - # def group_by_field - # @group_by_field ||= self.entries_custom_fields.detect { |f| f._name == self.group_by_field_name } - # end - protected def order_by_attribute @@ -155,7 +90,8 @@ module Locomotive def set_default_values self.order_by ||= 'created_at' - field = self.entries_custom_fields.find(self.label_field_id) rescue self.entries_custom_fields.first + self.label_field_id = self.entries_custom_fields.first._id if self.label_field_id.blank? + field = self.entries_custom_fields.find(self.label_field_id) self.label_field_name = field.name end @@ -177,3 +113,64 @@ module Locomotive end end + +# def list_or_group_contents +# if self.groupable? +# groups = self.contents.klass.send(:"group_by_#{self.group_by_field._alias}", :ordered_contents) +# +# # look for items with no category or unknown ones +# items_without_category = self.contents.find_all { |c| !self.group_by_field.category_ids.include?(c.send(self.group_by_field_name)) } +# if not items_without_category.empty? +# groups << { :name => nil, :items => items_without_category } +# else +# groups +# end +# else +# self.ordered_contents +# end +# end +# +# def latest_updated_contents +# self.contents.latest_updated.reject { |c| !c.persisted? } +# end +# +# def ordered_contents(conditions = {}) +# column = self.order_by.to_sym +# +# list = (if conditions.nil? || conditions.empty? +# self.contents +# else +# conditions_with_names = {} +# +# conditions.each do |key, value| +# # convert alias (key) to name +# field = self.entries_custom_fields.detect { |f| f._alias == key } +# +# case field.kind.to_sym +# when :category +# if (category_item = field.category_items.where(:name => value).first).present? +# conditions_with_names[field._name.to_sym] = category_item._id +# end +# else +# conditions_with_names[field._name.to_sym] = value +# end +# end +# +# self.contents.where(conditions_with_names) +# end).sort { |a, b| (a.send(column) && b.send(column)) ? (a.send(column) || 0) <=> (b.send(column) || 0) : 0 } +# +# return list if self.order_manually? +# +# self.asc_order? ? list : list.reverse +# end +# +# def sort_contents!(ids) +# ids.each_with_index do |id, position| +# self.contents.find(BSON::ObjectId(id))._position_in_list = position +# end +# self.save +# end +# +# def group_by_field +# @group_by_field ||= self.entries_custom_fields.detect { |f| f._name == self.group_by_field_name } +# end \ No newline at end of file diff --git a/app/presenters/locomotive/base_presenter.rb b/app/presenters/locomotive/base_presenter.rb index b6003297..f298cc88 100644 --- a/app/presenters/locomotive/base_presenter.rb +++ b/app/presenters/locomotive/base_presenter.rb @@ -1,7 +1,7 @@ class Locomotive::BasePresenter include ActionView::Helpers::SanitizeHelper - extend ActionView::Helpers::SanitizeHelper::ClassMethods + extend ActionView::Helpers::SanitizeHelper::ClassMethods include ActionView::Helpers::TextHelper include ActionView::Helpers::NumberHelper @@ -20,8 +20,6 @@ class Locomotive::BasePresenter def id self.source.persisted? || self.source.embedded? ? self.source._id.to_s : nil - # self.persisted? ? self.source._id.to_s : nil - # self.source._id.to_s end def ability? @@ -35,8 +33,8 @@ class Locomotive::BasePresenter def as_json(methods = nil) methods ||= self.included_methods {}.tap do |hash| - methods.map(&:to_sym).each do |meth| - hash[meth] = self.send(meth) rescue nil + methods.each do |meth| + hash[meth] = self.send(meth.to_sym) rescue nil end end end diff --git a/app/presenters/locomotive/content_entry_presenter.rb b/app/presenters/locomotive/content_entry_presenter.rb index 7a9d0c91..ad9baebe 100644 --- a/app/presenters/locomotive/content_entry_presenter.rb +++ b/app/presenters/locomotive/content_entry_presenter.rb @@ -3,20 +3,33 @@ module Locomotive delegate :_slug, :_position, :seo_title, :meta_keywords, :meta_description, :to => :source + # Returns the value of a field in the context of the current entry. + # + # @params [ CustomFields::Field ] field The field + # + # @returns [ Object ] The value of the field for the entry + # + def value_for(field) + getter = [*self.getters_for(field.name, field.type)].first.to_sym + self.source.send(getter) + end + + # Returns the list of getters for an entry + # + # @returns [ List ] a list of method names (string) + # def custom_fields_methods - source.custom_fields_recipe['rules'].map do |rule| - case rule['type'] - when 'select' then [rule['name'], "#{rule['name']}_id"] - when 'date' then "formatted_#{rule['name']}" - when 'file' then "#{rule['name']}_url" - else - rule['name'] - end + self.source.custom_fields_recipe['rules'].map do |rule| + self.getters_for rule['name'], rule['type'] end.flatten end + # Lists of all the attributes editable by a html form + # + # @returns [ List ] a list of attributes (string) + # def safe_attributes - source.custom_fields_recipe['rules'].map do |rule| + self.source.custom_fields_recipe['rules'].map do |rule| case rule['type'] when 'select' then "#{rule['name']}_id" when 'date' then "formatted_#{rule['name']}" @@ -27,6 +40,10 @@ module Locomotive end.flatten + %w(_slug seo_title meta_keywords meta_description) end + def errors + self.source.errors.to_hash.stringify_keys + end + def content_type_slug self.source.content_type.slug end @@ -36,7 +53,9 @@ module Locomotive end def included_methods - super + self.custom_fields_methods + %w(_slug _position content_type_slug _file_fields safe_attributes persisted) + default_list = %w(_slug _position content_type_slug _file_fields safe_attributes) + default_list << 'errors' if !!self.options[:include_errors] + super + self.custom_fields_methods + default_list end def method_missing(meth, *arguments, &block) @@ -47,5 +66,24 @@ module Locomotive end end + protected + + # Gets the names of the getter methods for a field. + # The names depend on the field type. + # + # @params [ String ] name Name of the field + # @params [ String ] type Type of the field + # + # @returns [ Object ] A string or an array of names + def getters_for(name, type) + case type + when 'select' then [name, "#{name}_id"] + when 'date' then "formatted_#{name}" + when 'file' then "#{name}_url" + else + name + end + end + end end \ No newline at end of file diff --git a/app/views/locomotive/content_types/_form.html.haml b/app/views/locomotive/content_types/_form.html.haml index cb253ec6..d3ff847c 100644 --- a/app/views/locomotive/content_types/_form.html.haml +++ b/app/views/locomotive/content_types/_form.html.haml @@ -33,6 +33,6 @@ = f.input :order_direction, :as => :select, :collection => options_for_order_direction, :include_blank => false, :wrapper_html => { :style => "#{'display: none' if @content_type.order_manually?}" } - = f.input :public_form_enabled, :as => :'Locomotive::Toggle' + = f.input :public_submission_enabled, :as => :'Locomotive::Toggle' - = f.input :public_form_accounts, :as => :select, :collection => options_for_account, :include_blank => false, :multiple => true, :wrapper_html => { :class => 'multiple', :style => (@content_type.public_form_enabled? ? '' : 'display: none') } + = f.input :public_submission_accounts, :as => :select, :collection => options_for_account, :include_blank => false, :multiple => true, :wrapper_html => { :class => 'multiple', :style => (@content_type.public_submission_enabled? ? '' : 'display: none') } diff --git a/app/views/locomotive/content_types/edit.html.haml b/app/views/locomotive/content_types/edit.html.haml index 1ce43ac3..52729ced 100644 --- a/app/views/locomotive/content_types/edit.html.haml +++ b/app/views/locomotive/content_types/edit.html.haml @@ -7,8 +7,8 @@ = render 'locomotive/shared/actions/contents' - content_for :buttons do - = local_action_button :show_items, content_entries_url(@content_type.slug_was), :class => 'show' - = local_action_button :new_item, new_content_entry_url(@content_type.slug_was), :class => 'new' + = local_action_button :show_entries, content_entries_url(@content_type.slug_was), :class => 'show' + = local_action_button :new_entry, new_content_entry_url(@content_type.slug_was), :class => 'new' %p!= t('.help') diff --git a/app/views/locomotive/custom_fields/_custom_form.html.haml b/app/views/locomotive/custom_fields/_custom_form.html.haml deleted file mode 100644 index ae427aa7..00000000 --- a/app/views/locomotive/custom_fields/_custom_form.html.haml +++ /dev/null @@ -1,10 +0,0 @@ -- highlighted_field_name = parent.highlighted_field_name rescue '' - -= form.inputs :name => title || :attributes do - - form.object.custom_fields.each do |field| - - highlighted = highlighted_field_name == field._name - - required = highlighted || field.required - - = render "/admin/custom_fields/types/#{field.kind}", :form => form, :parent => parent, :field => field, :required => required, :highlighted => highlighted - -= render '/admin/custom_fields/category_tmpl' \ No newline at end of file diff --git a/app/views/locomotive/custom_fields/_form.html.haml b/app/views/locomotive/custom_fields/_form.html.haml index 31c551dc..2629f783 100644 --- a/app/views/locomotive/custom_fields/_form.html.haml +++ b/app/views/locomotive/custom_fields/_form.html.haml @@ -42,7 +42,7 @@ = g.input :select_options, :as => :'Locomotive::Empty', :wrapper_html => { :class => 'extra select-options', :style => 'display: none' } - = g.input :text_formatting, :as => :select, :collection => options_for_text_formatting, :include_blank => false, :wrapper_html => { :class => 'extra text-formatting', :style => 'display: none' } + = g.input :text_formatting, :as => :select, :collection => options_for_text_formatting, :include_blank => false, :wrapper_html => { :class => 'extra text-formatting' }, :input_html => { :class => 'text_formatting' } %span.actions = link_to 'toggle', '#', :class => 'toggle' diff --git a/app/views/locomotive/custom_fields/types/_boolean.html.haml b/app/views/locomotive/custom_fields/types/_boolean.html.haml index d4e1d585..11159f00 100644 --- a/app/views/locomotive/custom_fields/types/_boolean.html.haml +++ b/app/views/locomotive/custom_fields/types/_boolean.html.haml @@ -1 +1,4 @@ -= f.input name, :label => field.label, :as => :'Locomotive::Toggle', :hint => field.hint \ No newline at end of file += f.input name, + :label => field.label, + :hint => field.hint, + :as => :'Locomotive::Toggle' \ No newline at end of file diff --git a/app/views/locomotive/custom_fields/types/_category.html.haml b/app/views/locomotive/custom_fields/types/_category.html.haml deleted file mode 100644 index e12b067e..00000000 --- a/app/views/locomotive/custom_fields/types/_category.html.haml +++ /dev/null @@ -1,4 +0,0 @@ -= form.custom_input field._alias.to_sym, :label => field.label, :hint => field.hint, :css => 'toggle', :required => required do - = form.select field._name.to_sym, field.ordered_category_items.collect { |item| [item.name, item.id] } - %button.button.light.edit-categories-link{ :type => 'button', :'data-url' => edit_admin_custom_field_path(parent.class.model_name.underscore, parent.slug, field) } - %span!= t('.edit_categories') diff --git a/app/views/locomotive/custom_fields/types/_date.html.haml b/app/views/locomotive/custom_fields/types/_date.html.haml index 9f5aee72..890005ba 100644 --- a/app/views/locomotive/custom_fields/types/_date.html.haml +++ b/app/views/locomotive/custom_fields/types/_date.html.haml @@ -1 +1,5 @@ -= f.input :"formatted_#{name}", :label => field.label, :hint => field.hint, :input_html => { :maxlength => 10 }, :wrapper_html => { :class => 'date' } \ No newline at end of file += f.input :"formatted_#{name}", + :label => field.label, + :hint => field.hint, + :wrapper_html => { :class => 'date' }, + :input_html => { :maxlength => 10 } diff --git a/app/views/locomotive/custom_fields/types/_file.html.haml b/app/views/locomotive/custom_fields/types/_file.html.haml index 344c6abe..fd2e1b45 100644 --- a/app/views/locomotive/custom_fields/types/_file.html.haml +++ b/app/views/locomotive/custom_fields/types/_file.html.haml @@ -1 +1,4 @@ -= f.input name, :label => field.label, :hint => field.hint, :as => :'Locomotive::File' \ No newline at end of file += f.input name, + :label => field.label, + :hint => field.hint, + :as => :'Locomotive::File' \ No newline at end of file diff --git a/app/views/locomotive/custom_fields/types/_select.html.haml b/app/views/locomotive/custom_fields/types/_select.html.haml index 3d61bd3e..89f4f9ba 100644 --- a/app/views/locomotive/custom_fields/types/_select.html.haml +++ b/app/views/locomotive/custom_fields/types/_select.html.haml @@ -1 +1,5 @@ -= f.input :"#{name}_id", :as => 'select', :collection => field.ordered_select_options.map { |option| [option.name, option.id] }, :label => field.label, :hint => field.hint \ No newline at end of file += f.input :"#{name}_id", + :label => field.label, + :hint => field.hint, + :as => 'select', + :collection => field.ordered_select_options.map { |option| [option.name, option.id] } \ No newline at end of file diff --git a/app/views/locomotive/custom_fields/types/_string.html.haml b/app/views/locomotive/custom_fields/types/_string.html.haml index d4ab6b70..0fc160a9 100644 --- a/app/views/locomotive/custom_fields/types/_string.html.haml +++ b/app/views/locomotive/custom_fields/types/_string.html.haml @@ -1 +1,4 @@ -= f.input name, :label => field.label, :hint => field.hint, :wrapper_html => { :class => "#{'highlighted' if highlighted}" } \ No newline at end of file += f.input name, + :label => field.label, + :hint => field.hint, + :wrapper_html => { :class => "#{'highlighted' if highlighted}" } \ No newline at end of file diff --git a/app/views/locomotive/custom_fields/types/_text.html.haml b/app/views/locomotive/custom_fields/types/_text.html.haml index 9d568b10..2258ed21 100644 --- a/app/views/locomotive/custom_fields/types/_text.html.haml +++ b/app/views/locomotive/custom_fields/types/_text.html.haml @@ -1 +1,5 @@ -= f.input field.name.to_sym, :label => field.label, :hint => field.hint, :as => :'Locomotive::Rte', :input_html => { :class => field.text_formatting } \ No newline at end of file += f.input field.name.to_sym, + :label => field.label, + :hint => field.hint, + :as => field.text_formatting == 'html' ? :'Locomotive::Rte' : 'text', + :input_html => { :class => field.text_formatting } \ No newline at end of file diff --git a/app/views/locomotive/notifications/new_content_entry.html.haml b/app/views/locomotive/notifications/new_content_entry.html.haml index cfc4f674..05844631 100644 --- a/app/views/locomotive/notifications/new_content_entry.html.haml +++ b/app/views/locomotive/notifications/new_content_entry.html.haml @@ -3,19 +3,20 @@ %hr %p - %b= t('.type', :type => @content_entry.content_type.name, :locale => @account.locale) + %b= t('.type', :type => @type.name, :locale => @account.locale) %br - %i= @content_entry.content_type.description + %i= @type.description %hr %ul - - @content_entry.custom_fields.each do |field| + - @type.entries_custom_fields.each do |field| + - value = @entry.value_for(field) %li %strong= field.label  -  %i - - if field.file? - = link_to File.basename(@content_entry.send(field.name).url), @content_entry.send(field.name).url + - if field.type == 'file' + = link_to File.basename(value), value - else - = @content_entry.send(field.name) + = value diff --git a/app/views/locomotive/sitemaps/show.xml.builder b/app/views/locomotive/public/sitemaps/show.xml.builder similarity index 100% rename from app/views/locomotive/sitemaps/show.xml.builder rename to app/views/locomotive/public/sitemaps/show.xml.builder diff --git a/config/locales/admin_ui.en.yml b/config/locales/admin_ui.en.yml index 06c6974b..e6a27bfb 100644 --- a/config/locales/admin_ui.en.yml +++ b/config/locales/admin_ui.en.yml @@ -222,14 +222,15 @@ en: content_types: index: new: new model + edit: edit model new: title: New model help: "Create your own data model (Projects, People, ...etc). Your model should have one field at least. The items created from this content type would have their first field mandatory." edit: title: Editing model help: "Your model should have one field at least. The items created from this content type would have their first field mandatory." - show_items: show items - new_item: new item + show_entries: show entries + new_entry: new entry form: order_by: created_at: 'By creation date' diff --git a/config/locales/formtastic.en.yml b/config/locales/formtastic.en.yml index e81c9a95..191825f7 100644 --- a/config/locales/formtastic.en.yml +++ b/config/locales/formtastic.en.yml @@ -41,7 +41,8 @@ en: default_site_template: "Use the default site template. Click here to upload a site template as a zip file instead." content_type: raw_item_template: Item template - public_form_accounts: Notified Accounts + public_submission_enabled: Public submission + public_submission_accounts: Notified Accounts "custom_fields/field": select_options: "Options" content_entry: @@ -95,8 +96,8 @@ en: name: "We suggest you to type the plural form of the model. Ex: Projects, Recipes, Posts, Articles, ...etc" slug: "It will be used as the name of the collection in the liquid templates. Ex: {{ contents.my_projects }}" raw_item_template: "You can customize the text displayed for each item in the list. Simply use Liquid. Ex: {{ entry.name }})" - public_form_enabled: "It is used to let people from outside to create new instances (example: messages in a contact form)" - public_form_accounts: "A notification email will be sent to each of the accounts listed above when a new instance is created" + public_submission_enabled: "It is used to let people from outside to create new entries (example: messages in a contact form)" + public_submission_accounts: "If the public submission option is enabled and for each entry created, sends a notification email tothe accounts listed above." "custom_fields/field": name: "Name of the property for liquid templates. Ex: {{ your_object.<name_of_your_field> }}" hint: "Text displayed in the model form just below the field" diff --git a/config/routes.rb b/config/routes.rb index dad86759..976cc3b9 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -41,8 +41,6 @@ Locomotive::Engine.routes.draw do put :sort, :on => :collection end - resources :api_contents, :path => 'api/:slug/contents', :controller => 'api_contents', :only => [:create] - resources :custom_fields, :path => 'custom/:parent/:slug/fields' resources :cross_domain_sessions, :only => [:new, :create] @@ -58,13 +56,16 @@ end Rails.application.routes.draw do # sitemap - match '/sitemap.xml' => 'locomotive/sitemaps#show', :format => 'xml' + match '/sitemap.xml' => 'locomotive/public/sitemaps#show', :format => 'xml' # robots.txt - match '/robots.txt' => 'locomotive/robots#show', :format => 'txt' + match '/robots.txt' => 'locomotive/public/robots#show', :format => 'txt' + + # public content entry submissions + resources :locomotive_entry_submissions, :controller => 'locomotive/public/content_entries', :path => 'entry_submissions/:slug' # magic urls - match '/' => 'locomotive/rendering#show' - match '*path/edit' => 'locomotive/rendering#edit' - match '*path' => 'locomotive/rendering#show' + match '/' => 'locomotive/public/rendering#show' + match '*path/edit' => 'locomotive/public/rendering#edit' + match '*path' => 'locomotive/public/rendering#show' end \ No newline at end of file diff --git a/doc/TODO b/doc/TODO index 754e9c0b..5fd224ec 100644 --- a/doc/TODO +++ b/doc/TODO @@ -8,9 +8,9 @@ x bugs: x undefined method `_selector' for # x editable_elements => view + handlebar template x editable_short_text => tinymce -- editable_file => +x editable_file => x backbone / handlebar - - new formtastic inputs + x new formtastic inputs x menu / submenu in full css3 (no images) x fix css in firefox x update page in ajax @@ -61,7 +61,11 @@ x edit my site x file x edit x destroy - - public_form (previously api something) + x public_form (previously api something) + x bug text formatting + - use list_or_group_entries instead of ordered_entries + - bug ui with contents popup + - custom_fields: use the appropriate icon to drag select options - disallow to click twice on the submit form button (spinner ?) - message to notify people if their browser is too old diff --git a/doc/changelogs/version_2.txt b/doc/changelogs/version_2.txt index 436e9d38..a875fb39 100644 --- a/doc/changelogs/version_2.txt +++ b/doc/changelogs/version_2.txt @@ -8,10 +8,13 @@ - content_types: - category => select - highlighted_field_name => highlighted_field_id (label_field_id) - - api_enabled => public_form_enabled - - api_accounts => public_form_accounts + - api_enabled => public_submission_enabled + - api_accounts => public_submission_accounts - contents (content_entries now) - _position_in_list => _position + - api_contents: + - url => entry_submissions + - params[:content] => params[:entries] collection, selector = Locomotive::ContentType.collection, Locomotive::ContentType.criteria.selector diff --git a/lib/locomotive.rb b/lib/locomotive.rb index e0e6c3ac..7cad1332 100644 --- a/lib/locomotive.rb +++ b/lib/locomotive.rb @@ -6,7 +6,6 @@ require 'locomotive/version' require 'locomotive/core_ext' require 'locomotive/configuration' require 'locomotive/logger' - require 'locomotive/formtastic' require 'locomotive/dragonfly' require 'locomotive/kaminari' @@ -15,7 +14,7 @@ require 'locomotive/mongoid' require 'locomotive/carrierwave' require 'locomotive/custom_fields' require 'locomotive/httparty' -require 'locomotive/responder' +require 'locomotive/action_controller' require 'locomotive/routing' require 'locomotive/regexps' require 'locomotive/render' @@ -76,11 +75,11 @@ module Locomotive self.add_middlewares # Load all the dynamic classes (custom fields) - # begin - # ContentType.all.collect(&:fetch_content_klass) - # rescue ::Mongoid::Errors::InvalidDatabase => e - # # let assume it's because of the first install (meaning no config.yml file) - # end + begin + ContentType.all.collect { |content_type| content_type.klass_with_custom_fields(:entries) } + rescue ::Mongoid::Errors::InvalidDatabase => e + # let assume it's because of the first install (meaning no config.yml file) + end end def self.add_middlewares diff --git a/lib/locomotive/action_controller.rb b/lib/locomotive/action_controller.rb new file mode 100644 index 00000000..4ba1eb57 --- /dev/null +++ b/lib/locomotive/action_controller.rb @@ -0,0 +1,3 @@ +require 'locomotive/action_controller/helpers' +require 'locomotive/action_controller/responder' +require 'locomotive/action_controller/public_responder' \ No newline at end of file diff --git a/lib/locomotive/action_controller/helpers.rb b/lib/locomotive/action_controller/helpers.rb new file mode 100644 index 00000000..251b170a --- /dev/null +++ b/lib/locomotive/action_controller/helpers.rb @@ -0,0 +1,66 @@ +module Locomotive + module ActionController + module Helpers + + extend ActiveSupport::Concern + + included do + helper_method :current_site_public_url, :switch_to_site_url, :public_page_url + end + + module InstanceMethods + + def set_locale + I18n.locale = current_locomotive_account.locale rescue Locomotive.config.default_locale + end + + def sections(key = nil) + if !key.nil? && key.to_sym == :sub + @locomotive_sections[:sub] || self.controller_name.dasherize + else + @locomotive_sections[:main] + end + end + + # ___ site/page urls builder ___ + + def current_site_public_url + request.protocol + request.host_with_port + end + + def switch_to_site_url(site, options = {}) + options = { :fullpath => true, :protocol => true }.merge(options) + + url = "#{site.subdomain}.#{Locomotive.config.domain}" + url += ":#{request.port}" if request.port != 80 + + url = File.join(url, request.fullpath) if options[:fullpath] + url = "http://#{url}" if options[:protocol] + url + end + + def public_page_url(page, options = {}) + if content = options.delete(:content) + File.join(current_site_public_url, page.fullpath.gsub('content_type_template', ''), content._slug) + else + File.join(current_site_public_url, page.fullpath) + end + end + + end + + module ClassMethods + + def sections(main, sub = nil) + before_filter do |c| + sub = sub.call(c) if sub.respond_to?(:call) + sections = { :main => main, :sub => sub } + c.instance_variable_set(:@locomotive_sections, sections) + end + end + + end + + end + end +end \ No newline at end of file diff --git a/lib/locomotive/action_controller/public_responder.rb b/lib/locomotive/action_controller/public_responder.rb new file mode 100644 index 00000000..261e9ccb --- /dev/null +++ b/lib/locomotive/action_controller/public_responder.rb @@ -0,0 +1,17 @@ +module Locomotive + module ActionController + class PublicResponder < ::ActionController::Responder + + def navigation_behavior(error) + if get? + raise error + elsif has_errors? && default_action + redirect_to navigation_location + else + redirect_to navigation_location + end + end + + end + end +end \ No newline at end of file diff --git a/lib/locomotive/action_controller/responder.rb b/lib/locomotive/action_controller/responder.rb new file mode 100644 index 00000000..38b0dd10 --- /dev/null +++ b/lib/locomotive/action_controller/responder.rb @@ -0,0 +1,63 @@ +module Locomotive + module ActionController + class Responder < ::ActionController::Responder + + include ::Responders::FlashResponder + + # by default flash_now messages if the resource has errors + def set_flash_now? + super || has_errors? + end + + def to_json + if get? + display resource + elsif has_errors? + with_flash_message(:alert) do + display resource.errors, :status => :unprocessable_entity + end + elsif post? + in_header = controller.request.headers['X-Flash'] == 'true' + with_flash_message(:notice, in_header) do + display resource, :location => api_location + end + elsif put? + with_flash_message do |message| + display resource, :status => :ok, :location => api_location + end + elsif delete? + with_flash_message do |message| + display resource, :status => :ok, :location => api_location + end + elsif has_empty_resource_definition? + display empty_resource, :status => :ok + else + with_flash_message do + head :ok + end + end + end + + protected + + def with_flash_message(type = :notice, in_header = true) + if in_header + set_flash_message! + message = controller.flash[type] + + controller.headers['X-Message'] = message + controller.headers['X-Message-Type'] = type + + yield if block_given? + + controller.flash.discard # reset flash messages ! + else + set_flash_message! + + yield if block_given? + end + end + + end + end +end \ No newline at end of file diff --git a/lib/locomotive/engine.rb b/lib/locomotive/engine.rb index edb5315d..b11ca83c 100644 --- a/lib/locomotive/engine.rb +++ b/lib/locomotive/engine.rb @@ -24,7 +24,7 @@ module Locomotive end initializer 'locomotive.action_controller' do |app| - ActionController::Base.wrap_parameters :format => [:json] + ::ActionController::Base.wrap_parameters :format => [:json] end end diff --git a/lib/locomotive/liquid/drops/content_types.rb b/lib/locomotive/liquid/drops/content_types.rb new file mode 100644 index 00000000..32ab5edb --- /dev/null +++ b/lib/locomotive/liquid/drops/content_types.rb @@ -0,0 +1,79 @@ +module Locomotive + module Liquid + module Drops + class ContentTypes < ::Liquid::Drop + + def before_method(meth) + type = @context.registers[:site].content_types.where(:slug => meth.to_s).first + ProxyCollection.new(type) + end + + end + + class ProxyCollection < ::Liquid::Drop + + def initialize(content_type) + @content_type = content_type + @collection = nil + end + + def first + self.collection.first + end + + def last + self.collection.last + end + + def each(&block) + self.collection.each(&block) + end + + def each_with_index(&block) + self.collection.each_with_index(&block) + end + + def count + @count ||= self.collection.count + end + + alias :size :count + alias :length :count + + def empty? + self.collection.empty? + end + + def any? + self.collection.any? + end + + def public_submission_url + @context.registers[:controller].main_app.locomotive_entry_submissions_url(@content_type.slug) + end + + def before_method(meth) + klass = @content_type.entries.klass # delegate to the proxy class + + if (meth.to_s =~ /^group_by_.+$/) == 0 + klass.send(meth, :ordered_entries) + else + Rails.logger.warn "[Liquid template] trying to call #{meth} on a content_type object" + # klass.send(meth) + end + end + + protected + + def paginate(options = {}) + @collection.page(options[:page]).per(options[:per_page]) + end + + def collection + @collection ||= @content_type.ordered_entries(@context['with_scope']) + end + end + + end + end +end diff --git a/lib/locomotive/liquid/drops/contents.rb b/lib/locomotive/liquid/drops/contents.rb index 65e27e51..3ba6841e 100644 --- a/lib/locomotive/liquid/drops/contents.rb +++ b/lib/locomotive/liquid/drops/contents.rb @@ -1,79 +1,81 @@ -module Locomotive - module Liquid - module Drops - class Contents < ::Liquid::Drop +# DEPRECATED - # TODO: refactoring - - def before_method(meth) - type = @context.registers[:site].content_types.where(:slug => meth.to_s).first - ProxyCollection.new(type) - end - - end - - class ProxyCollection < ::Liquid::Drop - - def initialize(content_type) - @content_type = content_type - @collection = nil - end - - def first - self.collection.first - end - - def last - self.collection.last - end - - def each(&block) - self.collection.each(&block) - end - - def each_with_index(&block) - self.collection.each_with_index(&block) - end - - def size - self.collection.size - end - - alias :length :size - - def empty? - self.collection.empty? - end - - def any? - self.collection.any? - end - - def api - { 'create' => @context.registers[:controller].send('api_contents_url', @content_type.slug) } - end - - def before_method(meth) - klass = @content_type.entries.klass # delegate to the proxy class - - if (meth.to_s =~ /^group_by_.+$/) == 0 - klass.send(meth, :ordered_contents) - else - klass.send(meth) - end - end - - protected - - def paginate(options = {}) - @collection = Kaminari.paginate_array(self.collection).page(options[:page]).per(options[:per_page]) - end - - def collection - @collection ||= @content_type.ordered_contents(@context['with_scope']) - end - end - - end - end -end +# module Locomotive +# module Liquid +# module Drops +# class Contents < ::Liquid::Drop +# +# # TODO: refactoring +# +# def before_method(meth) +# type = @context.registers[:site].content_types.where(:slug => meth.to_s).first +# ProxyCollection.new(type) +# end +# +# end +# +# class ProxyCollection < ::Liquid::Drop +# +# def initialize(content_type) +# @content_type = content_type +# @collection = nil +# end +# +# def first +# self.collection.first +# end +# +# def last +# self.collection.last +# end +# +# def each(&block) +# self.collection.each(&block) +# end +# +# def each_with_index(&block) +# self.collection.each_with_index(&block) +# end +# +# def size +# self.collection.size +# end +# +# alias :length :size +# +# def empty? +# self.collection.empty? +# end +# +# def any? +# self.collection.any? +# end +# +# def api +# { 'create' => @context.registers[:controller].send('api_contents_url', @content_type.slug) } +# end +# +# def before_method(meth) +# klass = @content_type.entries.klass # delegate to the proxy class +# +# if (meth.to_s =~ /^group_by_.+$/) == 0 +# klass.send(meth, :ordered_contents) +# else +# klass.send(meth) +# end +# end +# +# protected +# +# def paginate(options = {}) +# @collection = Kaminari.paginate_array(self.collection).page(options[:page]).per(options[:per_page]) +# end +# +# def collection +# @collection ||= @content_type.ordered_contents(@context['with_scope']) +# end +# end +# +# end +# end +# end diff --git a/lib/locomotive/render.rb b/lib/locomotive/render.rb index 3f925f19..0967a94a 100644 --- a/lib/locomotive/render.rb +++ b/lib/locomotive/render.rb @@ -61,7 +61,8 @@ module Locomotive assigns = { 'site' => current_site, 'page' => @page, - 'contents' => Locomotive::Liquid::Drops::Contents.new, + 'models' => Locomotive::Liquid::Drops::ContentTypes.new, + 'contents' => Locomotive::Liquid::Drops::ContentTypes.new, # DEPRECATED 'current_page' => self.params[:page], 'params' => self.params, 'path' => request.path, @@ -72,10 +73,12 @@ module Locomotive assigns.merge!(Locomotive.config.context_assign_extensions) - assigns.merge!(flash.to_hash.stringify_keys) # data from api + Rails.logger.debug flash.to_hash.stringify_keys.inspect + + assigns.merge!(flash.to_hash.stringify_keys) # data from public submissions if @page.templatized? # add instance from content type - assigns['content_entry'] = @content_entry + assigns['entry'] = @content_entry assigns[@page.content_type.slug.singularize] = @content_entry # just here to help to write readable liquid code end @@ -111,7 +114,7 @@ module Locomotive end def editing_page? - @editing + !!@editing end def page_status diff --git a/lib/locomotive/responder.rb b/lib/locomotive/responder.rb deleted file mode 100644 index e5ff427d..00000000 --- a/lib/locomotive/responder.rb +++ /dev/null @@ -1,61 +0,0 @@ -module Locomotive - class Responder < ::ActionController::Responder - - include ::Responders::FlashResponder - - # by default flash_now messages if the resource has errors - def set_flash_now? - super || has_errors? - end - - def to_json - if get? - display resource - elsif has_errors? - with_flash_message(:alert) do - display resource.errors, :status => :unprocessable_entity - end - elsif post? - in_header = controller.request.headers['X-Flash'] == 'true' - with_flash_message(:notice, in_header) do - display resource, :location => api_location - end - elsif put? - with_flash_message do |message| - display resource, :status => :ok, :location => api_location - end - elsif delete? - with_flash_message do |message| - display resource, :status => :ok, :location => api_location - end - elsif has_empty_resource_definition? - display empty_resource, :status => :ok - else - with_flash_message do - head :ok - end - end - end - - protected - - def with_flash_message(type = :notice, in_header = true) - if in_header - set_flash_message! - message = controller.flash[type] - - controller.headers['X-Message'] = message - controller.headers['X-Message-Type'] = type - - yield if block_given? - - controller.flash.discard # reset flash messages ! - else - set_flash_message! - - yield if block_given? - end - end - - end -end \ No newline at end of file diff --git a/locomotive_cms.gemspec b/locomotive_cms.gemspec index 57ded121..457c569e 100644 --- a/locomotive_cms.gemspec +++ b/locomotive_cms.gemspec @@ -17,7 +17,7 @@ Gem::Specification.new do |s| s.required_rubygems_version = '>= 1.3.6' s.rubyforge_project = 'nowarning' - s.add_dependency 'rails', '~> 3.0.10' + s.add_dependency 'rails', '~> 3.1.3' s.add_dependency 'warden' s.add_dependency 'devise', '1.3.4' s.add_dependency 'devise_bushido_authenticatable', '1.0.0.alpha10' From 01c5de36a52ec4ec786641d1b2e415c740b4dbf1 Mon Sep 17 00:00:00 2001 From: did Date: Mon, 9 Jan 2012 17:24:34 -0800 Subject: [PATCH 4/4] add the ui element to select the languages for a site --- .../views/content_entries/_form.js.coffee | 3 - .../views/current_site/edit_view.js.coffee | 22 ++++- .../views/import/show_view.js.coffee | 1 - .../locomotive/formtastic_changes.scss | 86 ++++++++++++------- .../locomotive/current_site_controller.rb | 2 + app/helpers/locomotive/sites_helper.rb | 10 +-- app/inputs/locomotive/locales_input.rb | 59 +++++++++++++ app/models/locomotive/extensions/site/i18n.rb | 53 ++++++++++++ app/models/locomotive/site.rb | 5 +- app/presenters/locomotive/site_presenter.rb | 4 +- .../locomotive/current_site/_form.html.haml | 16 ++-- config/locales/formtastic.en.yml | 3 + doc/TODO | 4 + .../install/templates/locomotive.rb | 3 + lib/locomotive/configuration.rb | 1 + lib/locomotive/mongoid/patches.rb | 23 ++--- spec/dummy/config/initializers/locomotive.rb | 3 + .../locomotive/backbone.modelbinding.js | 37 +++++--- .../javascripts/locomotive/backbone.sync.js | 5 ++ 19 files changed, 265 insertions(+), 75 deletions(-) create mode 100644 app/inputs/locomotive/locales_input.rb create mode 100644 app/models/locomotive/extensions/site/i18n.rb diff --git a/app/assets/javascripts/locomotive/views/content_entries/_form.js.coffee b/app/assets/javascripts/locomotive/views/content_entries/_form.js.coffee index 04ca2e82..a1a5427a 100644 --- a/app/assets/javascripts/locomotive/views/content_entries/_form.js.coffee +++ b/app/assets/javascripts/locomotive/views/content_entries/_form.js.coffee @@ -14,8 +14,6 @@ class Locomotive.Views.ContentEntries.FormView extends Locomotive.Views.Shared.F initialize: -> @model = new Locomotive.Models.ContentEntry(@options.content_entry) - console.log(@model.urlRoot) - window.foo = @model Backbone.ModelBinding.bind @ @@ -61,7 +59,6 @@ class Locomotive.Views.ContentEntries.FormView extends Locomotive.Views.Shared.F @$('li.input.highlighted > input[type=text]').slugify(target: @$('#content_entry__slug')) refresh_file_fields: -> - console.log('refresh_file_fields') _.each @_file_field_views, (view) => view.refresh() remove: -> diff --git a/app/assets/javascripts/locomotive/views/current_site/edit_view.js.coffee b/app/assets/javascripts/locomotive/views/current_site/edit_view.js.coffee index 46e0a70c..a7b42ee4 100644 --- a/app/assets/javascripts/locomotive/views/current_site/edit_view.js.coffee +++ b/app/assets/javascripts/locomotive/views/current_site/edit_view.js.coffee @@ -13,19 +13,39 @@ class Locomotive.Views.CurrentSite.EditView extends Locomotive.Views.Shared.Form initialize: -> @model = new Locomotive.Models.CurrentSite(@options.site) - Backbone.ModelBinding.bind @ + Backbone.ModelBinding.bind @, checkbox: 'class' window.foo = @model render: -> super() + @add_toggle_mode_for_locales() + + @make_locales_sortable() + @render_domains() @render_memberships() @enable_liquid_editing() + add_toggle_mode_for_locales: -> + @$('#site_locales_input .list input[type=checkbox]').bind 'change', (event) -> + el = $(event.target) + if el.is(':checked') + el.closest('.entry').addClass('selected') + else + el.closest('.entry').removeClass('selected') + + make_locales_sortable: -> + @sortable_locales_list = @$('#site_locales_input .list').sortable + items: '.entry' + tolerance: 'pointer' + update: => + list = _.map @$('#site_locales_input .list input:checked'), (el) => $(el).val() + @model.set locales: list + render_domains: -> @domains_view = new Locomotive.Views.Sites.DomainsView model: @model, errors: @options.errors diff --git a/app/assets/javascripts/locomotive/views/import/show_view.js.coffee b/app/assets/javascripts/locomotive/views/import/show_view.js.coffee index 0ad96d89..4dfe99e9 100644 --- a/app/assets/javascripts/locomotive/views/import/show_view.js.coffee +++ b/app/assets/javascripts/locomotive/views/import/show_view.js.coffee @@ -17,7 +17,6 @@ class Locomotive.Views.Import.ShowView extends Backbone.View @refresh_steps refresh_steps: (data) => - console.log 'refresh_steps: ....' window.foo = data window.bar = @ diff --git a/app/assets/stylesheets/locomotive/formtastic_changes.scss b/app/assets/stylesheets/locomotive/formtastic_changes.scss index 00f21398..44e7c8bd 100644 --- a/app/assets/stylesheets/locomotive/formtastic_changes.scss +++ b/app/assets/stylesheets/locomotive/formtastic_changes.scss @@ -279,6 +279,63 @@ form.formtastic { } } // li.string, li.password + &.locale, &.locales { + .list { + margin-left: 150px; + } + + &.locales { + label { + color: #8B8D9A; + } + } + + .entry { + float: left; + width: 212px; + + margin-left: 10px; + + &:first-child { + margin-left: 0px; + } + + label { + float: none; + display: inline-block; + width: auto; + position: relative; + + padding-left: 31px; + margin-left: 8px; + + font-weight: normal; + + img { + position: absolute; + top: 2px; + left: 0px; + } + } + + &.selected { + label { + color: #585A69; + } + &:first-child { + label { + font-weight: bold; + } + } + } // .entry.selected + + } // .entry + + .inline-hints { + clear: both; + } + } // > li.locale, li.locales + &.code { textarea, .CodeMirror-scroll { @@ -521,35 +578,6 @@ form.formtastic { } } // > li#site_memberships_input - &#account_locale_input { - .entry { - float: left; - width: 212px; - - margin-right: 10px; - - &:nth-child(3n) { - margin-right: 0px; - } - - label { - float: none; - display: inline-block; - width: auto; - position: relative; - - padding-left: 31px; - margin-left: 8px; - - img { - position: absolute; - top: 2px; - left: 0px; - } - } - } - } // > li#account_locale_input - &#account_sites_input { .entry { strong { diff --git a/app/controllers/locomotive/current_site_controller.rb b/app/controllers/locomotive/current_site_controller.rb index 25481ae3..30ead3e7 100644 --- a/app/controllers/locomotive/current_site_controller.rb +++ b/app/controllers/locomotive/current_site_controller.rb @@ -7,6 +7,8 @@ module Locomotive load_and_authorize_resource :class => 'Site' + helper 'Locomotive::Sites' + before_filter :filter_attributes respond_to :json, :only => :update diff --git a/app/helpers/locomotive/sites_helper.rb b/app/helpers/locomotive/sites_helper.rb index b41d06d1..614dfe86 100644 --- a/app/helpers/locomotive/sites_helper.rb +++ b/app/helpers/locomotive/sites_helper.rb @@ -1,11 +1,7 @@ module Locomotive::SitesHelper - # def error_on_domain(site, name) - # if (error = (site.errors[:domains] || []).detect { |n| n.include?(name) }) - # content_tag(:span, error, :class => 'inline-errors') - # else - # '' - # end - # end + def ordered_current_site_locales + current_site.locales + (Locomotive.config.site_locales - current_site.locales) + end end diff --git a/app/inputs/locomotive/locales_input.rb b/app/inputs/locomotive/locales_input.rb new file mode 100644 index 00000000..39d65a8f --- /dev/null +++ b/app/inputs/locomotive/locales_input.rb @@ -0,0 +1,59 @@ +module Locomotive + class LocalesInput < ::Formtastic::Inputs::CheckBoxesInput + + def to_html + input_wrapping do + label_html << + choices_group_wrapping do + collection.map { |choice| + choice_wrapping(choice_wrapping_html_options(choice)) do + choice_html(choice) + end + }.join("\n").html_safe + end + end + end + + def choices_group_wrapping(&block) + template.content_tag(:div, + template.capture(&block), + choices_group_wrapping_html_options + ) + end + + def choice_wrapping(html_options, &block) + template.content_tag(:div, + template.capture(&block), + html_options + ) + end + + def choice_html(choice) + check_box_without_hidden_input(choice) << + template.content_tag(:label, + choice_label(choice), + label_html_options.merge(:for => choice_input_dom_id(choice), :class => nil) + ) + end + + def choice_label(choice) + text = I18n.t("locomotive.my_account.edit.#{choice}") + template.image_tag("locomotive/icons/flags/#{choice}.png", :alt => text) << text + end + + def choices_group_wrapping_html_options + { :class => 'list' } + end + + def choice_wrapping_html_options(choice) + super.tap do |options| + options[:class] = "entry #{checked?(choice) ? 'selected' : ''}" + end + end + + def hidden_fields? + false + end + + end +end diff --git a/app/models/locomotive/extensions/site/i18n.rb b/app/models/locomotive/extensions/site/i18n.rb new file mode 100644 index 00000000..ec0081d5 --- /dev/null +++ b/app/models/locomotive/extensions/site/i18n.rb @@ -0,0 +1,53 @@ +module Locomotive + module Extensions + module Site + module I18n + + extend ActiveSupport::Concern + + included do + + ## fields ## + field :locales, :type => 'RawArray', :default => [] + + ## callbacks ## + # after_validation :add_missing_locales_for_all_pages + + end + + module InstanceMethods + + def locales=(array) + array = [] if array.blank?; super(array) + end + + def default_locale + self.locales.first || Locomotive.config.site_locales.first + end + + # protected + # + # def add_missing_locales_for_all_pages + # if self.locales_changed? + # list = self.pages.to_a + # + # while !list.empty? do + # page = list.pop + # begin + # page.send(:set_slug_and_fullpath_for_all_locales, self.locales) + # + # page.save + # + # rescue TypeError => e + # list.insert(0, page) + # end + # end + # end + # end + + end + + end + end + end +end \ No newline at end of file diff --git a/app/models/locomotive/site.rb b/app/models/locomotive/site.rb index 8346c8f6..abd8dad2 100644 --- a/app/models/locomotive/site.rb +++ b/app/models/locomotive/site.rb @@ -4,9 +4,10 @@ module Locomotive include Locomotive::Mongoid::Document ## Extensions ## - extend Extensions::Site::SubdomainDomains - extend Extensions::Site::FirstInstallation + extend Extensions::Site::SubdomainDomains + extend Extensions::Site::FirstInstallation include Extensions::Shared::Seo + include Extensions::Site::I18n ## fields ## field :name diff --git a/app/presenters/locomotive/site_presenter.rb b/app/presenters/locomotive/site_presenter.rb index de04a90b..272571be 100644 --- a/app/presenters/locomotive/site_presenter.rb +++ b/app/presenters/locomotive/site_presenter.rb @@ -1,7 +1,7 @@ module Locomotive class SitePresenter < BasePresenter - delegate :name, :subdomain, :domains, :robots_txt, :seo_title, :meta_keywords, :meta_description, :domains_without_subdomain, :to => :source + delegate :name, :locales, :subdomain, :domains, :robots_txt, :seo_title, :meta_keywords, :meta_description, :domains_without_subdomain, :to => :source def domain_name Locomotive.config.domain @@ -12,7 +12,7 @@ module Locomotive end def included_methods - super + %w(name domain_name subdomain domains robots_txt seo_title meta_keywords meta_description domains_without_subdomain memberships) + super + %w(name locales domain_name subdomain domains robots_txt seo_title meta_keywords meta_description domains_without_subdomain memberships) end end diff --git a/app/views/locomotive/current_site/_form.html.haml b/app/views/locomotive/current_site/_form.html.haml index 641b8a4c..1c910782 100644 --- a/app/views/locomotive/current_site/_form.html.haml +++ b/app/views/locomotive/current_site/_form.html.haml @@ -6,13 +6,9 @@ :plain { site: #{@site.to_json(:current_account => current_locomotive_account, :current_site => current_site)}, errors: #{@site.errors.to_json} } -= f.inputs :name => :information, :style => 'display: none' do - = f.input :name - -= f.inputs :name => :seo, :class => "inputs foldable #{'folded' if inputs_folded?(@site)}" do - = f.input :seo_title - = f.input :meta_keywords - = f.input :meta_description += f.inputs :name => :information do + = f.input :name, :wrapper_html => { :style => 'display: none' } + = f.input :locales, :as => '::Locomotive::Locales', :collection => ordered_current_site_locales, :input_html => { :class => 'locales' } - if can?(:point, Locomotive::Site) - if manage_subdomain_or_domains? @@ -22,6 +18,12 @@ - if manage_domains? = f.input :domains, :as => :'Locomotive::Empty' + += f.inputs :name => :seo, :class => "inputs foldable #{'folded' if inputs_folded?(@site)}" do + = f.input :seo_title + = f.input :meta_keywords + = f.input :meta_description + - if can?(:index, Locomotive::Membership) = f.inputs :name => :memberships do diff --git a/config/locales/formtastic.en.yml b/config/locales/formtastic.en.yml index 191825f7..55afef19 100644 --- a/config/locales/formtastic.en.yml +++ b/config/locales/formtastic.en.yml @@ -54,6 +54,8 @@ en: password_confirmation: New password confirmation page: seo_title: Title + site: + locales: Languages hints: page: @@ -68,6 +70,7 @@ en: snippet: slug: "You need to know it in order to insert the snippet inside a page" site: + locales: "Drag&drop a flag to the first position to make it the default one." seo_title: "Define a global value here which should be used as the value for the title tag in the head section." meta_keywords: "Meta keywords used within the head tag of the page. They are separated by a comma. Required for SEO." meta_description: "Meta description used within the head tag of the page. Required for SEO." diff --git a/doc/TODO b/doc/TODO index 5fd224ec..f2aaabe4 100644 --- a/doc/TODO +++ b/doc/TODO @@ -66,6 +66,10 @@ x edit my site - use list_or_group_entries instead of ordered_entries - bug ui with contents popup - custom_fields: use the appropriate icon to drag select options +- i18n + x add locales a site responds to + - locale switcher +- inline editor - disallow to click twice on the submit form button (spinner ?) - message to notify people if their browser is too old diff --git a/lib/generators/locomotive/install/templates/locomotive.rb b/lib/generators/locomotive/install/templates/locomotive.rb index 1445da84..e3b4b1e3 100644 --- a/lib/generators/locomotive/install/templates/locomotive.rb +++ b/lib/generators/locomotive/install/templates/locomotive.rb @@ -52,6 +52,9 @@ Locomotive.configure do |config| # default locale (for now, only en, de, fr, pt-BR and it are supported) config.default_locale = :en + # available locales suggested to "localize" a site. You will have to pick up at least one among that list. + # config.site_locales = %w{en de fr pt-BR it nl no es ru} + # tell if logs are enabled. Useful for debug purpose. config.enable_logs = true diff --git a/lib/locomotive/configuration.rb b/lib/locomotive/configuration.rb index f5dfe206..301c2cce 100644 --- a/lib/locomotive/configuration.rb +++ b/lib/locomotive/configuration.rb @@ -8,6 +8,7 @@ module Locomotive # :forbidden_paths => %w{layouts snippets stylesheets javascripts assets admin system api}, :reserved_slugs => %w{stylesheets javascripts assets admin images api pages edit}, :locales => %w{en de fr pt-BR it nl no es ru}, + :site_locales => %w{en de fr pt-BR it nl no es ru}, :cookie_key => '_locomotive_session', :enable_logs => false, :hosting => :auto, diff --git a/lib/locomotive/mongoid/patches.rb b/lib/locomotive/mongoid/patches.rb index c016e76f..3859ac8b 100644 --- a/lib/locomotive/mongoid/patches.rb +++ b/lib/locomotive/mongoid/patches.rb @@ -2,32 +2,33 @@ require 'mongoid' -module Mongoid - module Document +module Mongoid#:nodoc: + module Document #:nodoc: def as_json(options = {}) attrs = super(options) attrs["id"] = attrs["_id"] attrs end end -end -# Limit feature for embedded documents + module Fields #:nodoc: + module Internal #:nodoc: + class RawArray < Mongoid::Fields::Internal::Array + def resizable?; false; end + end + end -module Mongoid #:nodoc: + class RawArray < ::Array; end + end # without callback feature - module Callbacks - - module ClassMethods - + module Callbacks #:nodoc: + module ClassMethods #:nodoc: def without_callback(*args, &block) skip_callback(*args) yield set_callback(*args) end - end - end end \ No newline at end of file diff --git a/spec/dummy/config/initializers/locomotive.rb b/spec/dummy/config/initializers/locomotive.rb index 7bd49141..3431b09d 100644 --- a/spec/dummy/config/initializers/locomotive.rb +++ b/spec/dummy/config/initializers/locomotive.rb @@ -53,6 +53,9 @@ Locomotive.configure do |config| # default locale (for now, only en, de, fr, pt-BR and it are supported) config.default_locale = :en + # available locales suggested to "localize" a site. You will have to pick up at least one among that list. + config.site_locales = %w{en de fr pt-BR it nl no es ru} + # tell if logs are enabled. Useful for debug purpose. config.enable_logs = true diff --git a/vendor/assets/javascripts/locomotive/backbone.modelbinding.js b/vendor/assets/javascripts/locomotive/backbone.modelbinding.js index 5de03b79..6bd007f3 100644 --- a/vendor/assets/javascripts/locomotive/backbone.modelbinding.js +++ b/vendor/assets/javascripts/locomotive/backbone.modelbinding.js @@ -364,26 +364,39 @@ Backbone.ModelBinding = (function(Backbone, _, $){ } // console.log(attribute_name); + var isArray = _.isArray(model.get(attribute_name)) + var modelChange = function(model, val){ - if (val){ + var checked = val; + if (isArray) + checked = _.include(val, element.val()); + + if (checked) element.attr("checked", "checked"); - } - else{ + else element.removeAttr("checked"); - } }; - var setModelValue = function(attr_name, value){ + var setModelValue = function(attr_name, checked, value){ var data = {}; - data[attr_name] = value; + if (isArray) { + var array = model.get(attr_name); + if (array == null) array = []; + if (checked) + array.push(value); + else + array = _.without(array, value); + data[attr_name] = array; + } else + data[attr_name] = value; model.set(data); }; var elementChange = function(ev){ - // console.log('[SELECT] elementChange'); + // console.log('[CHECKBOX] elementChange'); var changedElement = view.$(ev.target); var checked = changedElement.is(":checked")? true : false; - setModelValue(attribute_name, checked); + setModelValue(attribute_name, checked, changedElement.val()); }; modelBinder.registerModelBinding(model, attribute_name, modelChange); @@ -393,16 +406,16 @@ Backbone.ModelBinding = (function(Backbone, _, $){ if (attr_exists) { // set the default value on the form, from the model var attr_value = model.get(attribute_name); - if (typeof attr_value !== "undefined" && attr_value !== null && attr_value != false) { + if (isArray && !_.isArray(attr_value)) attr_value = []; + if (typeof attr_value !== "undefined" && attr_value !== null && (attr_value == true || _.include(attr_value, element.val()))) { element.attr("checked", "checked"); - } - else{ + }else{ element.removeAttr("checked"); } } else { // bind the form's value to the model var checked = element.is(":checked")? true : false; - setModelValue(attribute_name, checked); + setModelValue(attribute_name, checked, element.val()); } }); }; diff --git a/vendor/assets/javascripts/locomotive/backbone.sync.js b/vendor/assets/javascripts/locomotive/backbone.sync.js index be78bda2..99223689 100644 --- a/vendor/assets/javascripts/locomotive/backbone.sync.js +++ b/vendor/assets/javascripts/locomotive/backbone.sync.js @@ -51,6 +51,11 @@ var _buildParams = function(prefix, obj, fn) { // code grabbed from jquery if (jQuery.isArray(obj)) { + if (obj.length == 0) { // empty arrays + fn(prefix, obj); + return; + } + jQuery.each(obj, function(i, v) { if (/\[\]$/.test(prefix)) { // rbracket fn(prefix, v);