diff --git a/app/assets/javascripts/locomotive/views/content_entries/_form_view.js.coffee b/app/assets/javascripts/locomotive/views/content_entries/_form_view.js.coffee index 12b1edd3..19267aa3 100644 --- a/app/assets/javascripts/locomotive/views/content_entries/_form_view.js.coffee +++ b/app/assets/javascripts/locomotive/views/content_entries/_form_view.js.coffee @@ -18,8 +18,6 @@ class Locomotive.Views.ContentEntries.FormView extends Locomotive.Views.Shared.F initialize: -> @model ||= new Locomotive.Models.ContentEntry(@options.content_entry) - window.foo = @model - Backbone.ModelBinding.bind @ render: -> @@ -61,7 +59,7 @@ class Locomotive.Views.ContentEntries.FormView extends Locomotive.Views.Shared.F @_file_field_views.push(view) - @$("##{@model.paramRoot}_#{name}_input").append(view.render().el) + @$("##{@model.paramRoot}_#{name}_input label").after(view.render().el) enable_has_many_fields: -> _.each @model.get('has_many_custom_fields'), (field) => 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 f150b6c9..7420a68b 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 @@ -12,6 +12,8 @@ class Locomotive.Views.ContentTypes.FormView extends Locomotive.Views.Shared.For initialize: -> @model = new Locomotive.Models.ContentType(@options.content_type) + window.foo = @model + Backbone.ModelBinding.bind @ render: -> diff --git a/app/controllers/locomotive/public/content_entries_controller.rb b/app/controllers/locomotive/public/content_entries_controller.rb index e4a0c418..8544cac1 100644 --- a/app/controllers/locomotive/public/content_entries_controller.rb +++ b/app/controllers/locomotive/public/content_entries_controller.rb @@ -13,7 +13,7 @@ module Locomotive respond_to :html, :json def create - @entry = @content_type.entries.create(params[:entry]) + @entry = @content_type.entries.create(params[:entry] || params[:content]) flash[@content_type.slug.singularize] = @entry.to_presenter(:include_errors => true).as_json respond_with @entry, :location => self.callback_url end @@ -34,7 +34,7 @@ module Locomotive end def callback_url - @entry.errors.empty? ? params[:success_callback] : params[:error_callback] + (@entry.errors.empty? ? params[:success_callback] : params[:error_callback]) || main_app.root_path end def sanitize_entry_params diff --git a/app/inputs/locomotive/file_input.rb b/app/inputs/locomotive/file_input.rb index 5e578daa..ef8a469f 100644 --- a/app/inputs/locomotive/file_input.rb +++ b/app/inputs/locomotive/file_input.rb @@ -18,12 +18,12 @@ module Locomotive def file_wrapper_html template.content_tag(:script, - template.content_tag(:span, %( + %( {{#if url}} #{with_file_html} {{else}} #{without_file_html} - {{/if}}).html_safe, :class => 'file'), + {{/if}}).html_safe, :type => 'text/html', :id => "#{method}_file_input") end diff --git a/app/models/locomotive/extensions/page/editable_elements.rb b/app/models/locomotive/extensions/page/editable_elements.rb index 65fd3686..61d970f4 100644 --- a/app/models/locomotive/extensions/page/editable_elements.rb +++ b/app/models/locomotive/extensions/page/editable_elements.rb @@ -8,11 +8,11 @@ module Locomotive included do embeds_many :editable_elements, :class_name => 'Locomotive::EditableElement' - after_save :remove_disabled_editable_elements + after_save :remove_disabled_editable_elements # editable file callbacks - after_save :store_file_sources! - before_save :write_file_source_identifiers + after_save :store_file_sources! + before_save :write_file_source_identifiers after_destroy :remove_file_sources! accepts_nested_attributes_for :editable_elements diff --git a/app/models/locomotive/extensions/page/redirect.rb b/app/models/locomotive/extensions/page/redirect.rb index b2672d02..8b9f2300 100644 --- a/app/models/locomotive/extensions/page/redirect.rb +++ b/app/models/locomotive/extensions/page/redirect.rb @@ -8,8 +8,8 @@ module Locomotive included do ## fields ## - field :redirect, :type => Boolean, :default => false - field :redirect_url, :type => String + field :redirect, :type => Boolean, :default => false + field :redirect_url, :type => String ## validations ## validates_presence_of :redirect_url, :if => :redirect diff --git a/app/models/locomotive/snippet.rb b/app/models/locomotive/snippet.rb index 5197445d..0721183b 100644 --- a/app/models/locomotive/snippet.rb +++ b/app/models/locomotive/snippet.rb @@ -37,7 +37,6 @@ module Locomotive protected def normalize_slug - # TODO: refactor it self.slug = self.name.clone if self.slug.blank? && self.name.present? self.slug.permalink! if self.slug.present? end diff --git a/app/views/locomotive/content_entries/index.html.haml b/app/views/locomotive/content_entries/index.html.haml index d984a200..2d0bf235 100644 --- a/app/views/locomotive/content_entries/index.html.haml +++ b/app/views/locomotive/content_entries/index.html.haml @@ -1,8 +1,5 @@ - title t('.title', :type => @content_type.name.capitalize) -- content_for :submenu do - = render 'locomotive/shared/menu/contents' - - content_for :actions do = render 'locomotive/shared/actions/contents' @@ -24,6 +21,11 @@ - else = render 'list', :content_type => @content_type, :entries => @content_entries +- # Note: submenu has to be here in order to have the previous entries correctly rendered since we do not return +- # all the attributes of the content types in the following code (causing stale documents) +- content_for :submenu do + = render 'locomotive/shared/menu/contents' + - if can?(:manage, Locomotive::ContentType) #local-actions-bottom-bar %p.tleft diff --git a/lib/locomotive.rb b/lib/locomotive.rb index 0ab0d1eb..e675e9d3 100644 --- a/lib/locomotive.rb +++ b/lib/locomotive.rb @@ -99,10 +99,6 @@ module Locomotive method = :"enable_#{target}" self.send(method) if self.respond_to?(method) - - # if (!Rails.env.test? && !Rails.env.development?) && !self.config.hosting.blank? && self.respond_to?(:"enable_#{self.config.hosting}") - # self.send(:"enable_#{self.config.hosting}") - # end end def self.define_subdomain_and_domains_options diff --git a/lib/locomotive/liquid/drops/content_types.rb b/lib/locomotive/liquid/drops/content_types.rb index 68996215..9346abb4 100644 --- a/lib/locomotive/liquid/drops/content_types.rb +++ b/lib/locomotive/liquid/drops/content_types.rb @@ -21,13 +21,18 @@ module Locomotive @context.registers[:controller].main_app.locomotive_entry_submissions_url(@content_type.slug) end + def api + Locomotive.log :warn, "[Liquid template] the api for content_types has been deprecated and replaced by public_submission_url instead." + { 'create' => public_submission_url } + 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) + if (meth.to_s =~ /^group_by_(.+)$/) == 0 + klass.send(:group_by_select_option, $1, @content_type.order_by_definition) else - Rails.logger.warn "[Liquid template] trying to call #{meth} on a content_type object" + Locomotive.log :warn, "[Liquid template] trying to call #{meth} on a content_type object" end end diff --git a/script/upgrade.rb b/script/upgrade.rb index 85acf6f7..0d78a6cb 100755 --- a/script/upgrade.rb +++ b/script/upgrade.rb @@ -5,21 +5,43 @@ rescue LoadError puts 'You must `gem install bundler` and `bundle install` to run rake tasks' end +# ================ GLOBAL VARIABLES ============== + +$database = 'locomotive_hosting_production' + +$default_locale = 'en' +# $locale_exceptions = {} + +# Example: +$locale_exceptions = { + '4c082a9393d4330812000002' => 'fr', + '4c2330706f40d50ae2000005' => 'fr', + '4dc07643d800a53aea00035a' => 'fr', + '4eb6aca89a976a0001000ebb' => 'fr' +} + +def get_locale(site_id) + $locale_exceptions[site_id.to_s] || $default_locale +end + +# ================ MONGODB ============== + require 'mongoid' Mongoid.configure do |config| - name = 'locomotive_hosting_production' + name = $database host = 'localhost' - # config.master = Mongo::Connection.new.db(name) - config.master = Mongo::Connection.new('localhost', '27017', :logger => Logger.new($stdout)).db(name) + config.master = Mongo::Connection.new.db(name) + # config.master = Mongo::Connection.new('localhost', '27017', :logger => Logger.new($stdout)).db(name) end +db = Mongoid.config.master + + puts "***************************************" puts "[LocomotiveCMS] Upgrade from 1.0 to 2.0" puts "***************************************\n\n" -db = Mongoid.config.master - # assets -> locomotive_content_assets if collection = db.collections.detect { |c| c.name == 'assets' } new_collection = db.collections.detect { |c| c.name == 'locomotive_content_assets' } @@ -49,31 +71,29 @@ if collection = db.collections.detect { |c| c.name == 'content_types' } }, :multi => true) collection.find.each do |content_type| - puts "_________________________________" - puts "[content_type: #{content_type['name']}] = #{content_type.keys.inspect}" - + locale = get_locale(content_type['site_id']) label_field_name = '' + recipe = { 'name' => "Entry#{content_type['_id']}", 'version' => content_type['content_custom_fields_version'], 'rules' => [] } + rule_options = {} operations = { '$set' => {}, '$unset' => {} } contents = content_type['contents'] custom_fields = content_type['entries_custom_fields'] - puts "\n*** field keys = #{custom_fields.first.keys.inspect} ***\n\n" - # fields custom_fields.each_with_index do |field, index| - # puts "field #{field['_alias']}.#{index} (#{field['kind']})" - - next if field['kind'].blank? # already done - + name, type = field['_alias'], field['kind'].downcase class_name = "Locomotive::Entry#{field['target'][-24,24]}" if field['target'] case field['kind'] when 'category' + type = 'select' operations['$set'].merge!("entries_custom_fields.#{index}.type" => 'select') when 'has_one' + type = 'belongs_to' operations['$set'].merge!("entries_custom_fields.#{index}.type" => 'belongs_to') when 'has_many' if field['reverse_lookup'] + type = 'has_many' operations['$set'].merge!("entries_custom_fields.#{index}.type" => 'has_many') # reverse_lookup -> inverse_of => hmmmmmmm @@ -83,6 +103,7 @@ if collection = db.collections.detect { |c| c.name == 'content_types' } end end else + type = 'many_to_many' operations['$set'].merge!("entries_custom_fields.#{index}.type" => 'many_to_many') end end @@ -108,20 +129,38 @@ if collection = db.collections.detect { |c| c.name == 'content_types' } end operations['$set'].merge!({ - "entries_custom_fields.#{index}.name" => field['_alias'], - "entries_custom_fields.#{index}.type" => field['kind'] + "entries_custom_fields.#{index}.name" => field['_alias'], + "entries_custom_fields.#{index}.type" => type, + "entries_custom_fields.#{index}._type" => 'Locomotive::ContentTypeEntryField', + "entries_custom_fields.#{index}.localized" => false }) - operations['$set'].merge!({ - "entries_custom_fields.#{index}.select_options" => field['category_items'] - }) if field['kind'] == 'category' + if field['kind'] == 'category' + options = field['category_items'].map do |attributes| + { + '_id' => attributes['_id'], + 'name' => { locale => attributes['name'] }, + 'position' => attributes['position'] + } + end + rule_options['select_options'] = options + operations['$set'].merge!("entries_custom_fields.#{index}.select_options" => options) + end operations['$unset'].merge!({ "entries_custom_fields.#{index}._name" => '1', "entries_custom_fields.#{index}._alias" => '1', "entries_custom_fields.#{index}.kind" => '1', - "entries_custom_fields.#{index}.category_items" => '1' + "entries_custom_fields.#{index}.category_items" => '1', + "entries_custom_fields.#{index}.format" => '1' }) + + recipe['rules'] << { + 'name' => name, + 'type' => type, + 'required' => field['required'] || false, + 'localized' => false + }.merge(rule_options) end operations['$set'].merge!({ @@ -134,19 +173,15 @@ if collection = db.collections.detect { |c| c.name == 'content_types' } }) # contents - if contents.nil? - puts "CONTENTS SKIPPED" - next - end - - contents.each_with_index do |content| + (contents || []).each_with_index do |content| attributes = content.clone.keep_if { |k, v| %w(_id _slug seo_title meta_description meta_keywords _visible created_at updated_at).include?(k) } attributes.merge!({ - 'content_type_id' => content_type['_id'], - 'site_id' => content_type['site_id'], - '_position' => content['_position_in_list'], - '_type' => "Locomotive::Entry#{content_type['_id']}", - '_label_field_name' => label_field_name + 'content_type_id' => content_type['_id'], + 'site_id' => content_type['site_id'], + '_position' => content['_position_in_list'], + '_type' => "Locomotive::Entry#{content_type['_id']}", + '_label_field_name' => label_field_name, + 'custom_fields_recipe' => recipe }) custom_fields.each do |field| @@ -156,7 +191,7 @@ if collection = db.collections.detect { |c| c.name == 'content_types' } when 'string', 'text', 'boolean', 'date' attributes[name] = content[_name] when 'file' - attributes[name] = "#{content[_name]}_filename" + attributes[name] = content["#{_name}_filename"] when 'category', 'has_one' attributes["#{name}_id"] = content[_name] when 'has_many' @@ -169,34 +204,121 @@ if collection = db.collections.detect { |c| c.name == 'content_types' } end # insert document - # puts "[INSERTING] ===> #{attributes.inspect}" contents_collection.insert attributes end - # TODO: change highlighted_field_name + for each field, change category -> select - # save content_type collection.update({ '_id' => content_type['_id'] }, operations) - - # puts operations.inspect - - puts "================================= END =========================" - - # raise 'END' end - collection.update({}, { - '$unset' => { - 'contents' => '1' - } - }, :multi => true) + collection.update({}, { '$unset' => { 'contents' => '1' } }, :multi => true) end +# sites -> locomotive_sites +if collection = db.collections.detect { |c| c.name == 'sites' } + new_collection = db.collections.detect { |c| c.name == 'locomotive_sites' } + new_collection.drop if new_collection + collection.rename 'locomotive_sites' -# TODO -# x relaunch with a fresh db -# x inverse_of can not work if we commit changes before -# x insert contents -# - assets -# - -# + # localize attributes + collection.find.each do |site| + locale = get_locale(site['_id']) + + attributes = { 'locales' => [locale] } + + %w(seo_title meta_keywords meta_description).each do |attr| + attributes[attr] = { locale => site[attr] } + end + + collection.update({ '_id' => site['_id'] }, { '$set' => attributes }) + end +end + +# snippets -> locomotive_snippets +if collection = db.collections.detect { |c| c.name == 'snippets' } + new_collection = db.collections.detect { |c| c.name == 'locomotive_snippets' } + new_collection.drop if new_collection + collection.rename 'locomotive_snippets' + + # localize template + collection.find.each do |snippet| + locale = get_locale(snippet['site_id']) + + collection.update({ '_id' => snippet['_id'] }, { '$set' => { 'template' => { locale => snippet['template'] } } }) + end +end + +# theme_assets -> locomotive_theme_assets +if collection = db.collections.detect { |c| c.name == 'theme_assets' } + new_collection = db.collections.detect { |c| c.name == 'locomotive_theme_assets' } + new_collection.drop if new_collection + collection.rename 'locomotive_theme_assets' +end + +# accounts -> locomotive_accounts +if collection = db.collections.detect { |c| c.name == 'accounts' } + new_collection = db.collections.detect { |c| c.name == 'locomotive_accounts' } + new_collection.drop if new_collection + collection.rename 'locomotive_accounts' +end + +# pages -> locomotive_pages +if collection = db.collections.detect { |c| c.name == 'pages' } + new_collection = db.collections.detect { |c| c.name == 'locomotive_pages' } + new_collection.drop if new_collection + collection.rename 'locomotive_pages' + + parents_table = {} + + collection.find.each do |page| + parents_table[page['_id']] = page['parent_id'] + locale = get_locale(page['site_id']) + + modifications, removals = {}, {} + + %w(title slug fullpath raw_template serialized_template template_dependencies snippet_dependencies seo_title meta_keywords meta_description).each do |attr| + modifications[attr] = { locale => page[attr] } + end + + if page['templatized'] + modifications['target_klass_name'] = "Locomotive::Entry#{page['content_type_id']}" + removals['content_type_id'] = '1' + end + + # editable elements + (page['editable_elements'] || []).each_with_index do |editable_element, index| + modifications["editable_elements.#{index}._type"] = "Locomotive::#{editable_element['_type']}" + modifications["editable_elements.#{index}.content"] = { locale => editable_element['content'] } + + if editable_element['_type'] == 'EditableFile' + modifications["editable_elements.#{index}.source"] = { locale => editable_element['source_filename'] } + removals["editable_elements.#{index}.source_filename"] = '1' + end + end + + if page['depth'] == 0 && page['fullpath'] == '404' + modifications['position'] = 1 + end + + collection.update({ '_id' => page['_id'] }, { '$set' => modifications, '$unset' => removals }) + end + + # set parent ids + collection.find.each do |page| + parent_ids, page_cursor = [], page['_id'] + + while !parents_table[page_cursor].nil? + parent_ids << parents_table[page_cursor] + page_cursor = parents_table[page_cursor] + end + + collection.update({ '_id' => page['_id'] }, { '$set' => { 'parent_ids' => parent_ids.reverse } }) + end + + collection.update({}, { '$unset' => { 'parts' => '1', 'path' => '1', 'layout_id' => '1' } }, { :multi => true }) +end + +# some cleaning +%w(asset_collections liquid_templates delayed_backend_mongoid_jobs).each do |name| + db.drop_collection name +end diff --git a/spec/dummy/config/initializers/locomotive.rb b/spec/dummy/config/initializers/locomotive.rb index ad405316..27e8a03a 100644 --- a/spec/dummy/config/initializers/locomotive.rb +++ b/spec/dummy/config/initializers/locomotive.rb @@ -10,6 +10,7 @@ Locomotive.configure do |config| # and the multi_site_domain value (ex: website_1.locomotivehosting.com). multi_sites.domain = 'engine.dev' #'myhostingplatform.com' # multi_sites.domain = 'example.com' + # multi_sites.domain = 'locomotivehosting.fr' # define the reserved subdomains # Ex: diff --git a/spec/dummy/config/mongoid.yml b/spec/dummy/config/mongoid.yml index 7416363a..17611c5e 100644 --- a/spec/dummy/config/mongoid.yml +++ b/spec/dummy/config/mongoid.yml @@ -17,5 +17,4 @@ test: production: <<: *defaults - # database: locomotive_engine_production - database: locomotive_hosting_production + database: locomotive_engine_production