From d1bb45d7c8530b210f760df6a071929e9a3e36c0 Mon Sep 17 00:00:00 2001 From: did Date: Thu, 22 Dec 2011 01:31:33 +0100 Subject: [PATCH] polishing the UI for the content types, refactoring still in progress --- Gemfile | 4 +- Gemfile.lock | 18 +- .../views/content_types/_form_view.js.coffee | 31 +++ .../views/shared/form_view.js.coffee | 9 +- .../locomotive/formtastic_changes.scss | 23 +- .../locomotive/content_types_controller.rb | 2 +- app/helpers/locomotive/accounts_helper.rb | 4 + .../locomotive/custom_fields_helper.rb | 243 +++++++++--------- app/inputs/locomotive/small_code_input.rb | 22 ++ app/models/locomotive/content_type.rb | 18 +- .../extensions/content_type/item_template.rb | 4 +- .../locomotive/content_types/_form.html.haml | 35 +-- config/locales/formtastic.en.yml | 12 +- doc/TODO | 4 +- doc/changelogs/version_2.txt | 7 +- 15 files changed, 264 insertions(+), 172 deletions(-) create mode 100644 app/inputs/locomotive/small_code_input.rb diff --git a/Gemfile b/Gemfile index b8662442..3fbe0bb7 100644 --- a/Gemfile +++ b/Gemfile @@ -13,8 +13,8 @@ gem 'bson_ext', '~> 1.4.0' gem 'mongoid', '~> 2.3.3' 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 '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' diff --git a/Gemfile.lock b/Gemfile.lock index 55583f23..76113e6f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -7,6 +7,16 @@ GIT fssm (>= 0.2.7) sass (~> 3.1) +GIT + remote: git://github.com/locomotivecms/custom_fields.git + revision: 8bf202d6e0294ca2050ecd7ec44dcc4d570cb7fd + branch: experimental + specs: + custom_fields (2.0.0.rc1) + activesupport (~> 3.1.3) + carrierwave-mongoid (~> 0.1.3) + mongoid (~> 2.3.4) + GIT remote: git://github.com/plataformatec/devise.git revision: ede004169c6af7416f8c4e3fc29a653bee133f60 @@ -28,14 +38,6 @@ GIT specs: locomotive_mongoid_acts_as_tree (0.1.5.7) -PATH - remote: ../gems/custom_fields - specs: - custom_fields (2.0.0.rc1) - activesupport (~> 3.1.3) - carrierwave-mongoid (~> 0.1.3) - mongoid (~> 2.3.4) - GEM remote: http://rubygems.org/ specs: 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 2078218f..8ddacba9 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,6 +23,12 @@ class Locomotive.Views.ContentTypes.FormView extends Locomotive.Views.Shared.For @slugify_name() # slugify the slug field from name + @enable_liquid_editing() # turn textarea into editable liquid code zone + + @enable_public_form_checkbox() + + @enable_order_by_toggler() + return @ render_custom_fields: -> @@ -33,8 +39,33 @@ class Locomotive.Views.ContentTypes.FormView extends Locomotive.Views.Shared.For slugify_name: -> @$('#content_type_name').slugify(target: @$('#content_type_slug'), sep: '_') + enable_liquid_editing: -> + input = @$('#content_type_raw_item_template') + @editor = CodeMirror.fromTextArea input.get()[0], + mode: 'liquid' + autoMatchParens: false + lineNumbers: false + passDelay: 50 + tabMode: 'shift' + 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_order_by_toggler: -> + @$('#content_type_order_by_input').bind 'change', (event) => + target = @$('#content_type_order_direction_input') + if $(event.target).val() == '_position_in_list' + target.hide() + else + target.show() + show_error: (attribute, message, html) -> if attribute == 'contents_custom_fields' + return if _.isEmpty(message) for _message, index in message @custom_fields_view._entry_views[index].show_error(_message[0]) else diff --git a/app/assets/javascripts/locomotive/views/shared/form_view.js.coffee b/app/assets/javascripts/locomotive/views/shared/form_view.js.coffee index c6ee4aa8..ac69cea5 100644 --- a/app/assets/javascripts/locomotive/views/shared/form_view.js.coffee +++ b/app/assets/javascripts/locomotive/views/shared/form_view.js.coffee @@ -91,13 +91,16 @@ class Locomotive.Views.Shared.FormView extends Backbone.View anchor.after(html) _enable_checkbox: (name, options) -> - @$('li#page_' + name + '_input input[type=checkbox]').checkToggle + options ||= {} + model_name = options.model_name || @model.paramRoot + + @$("li##{model_name}_#{name}_input input[type=checkbox]").checkToggle on_callback: => - _.each options.features, (exp) -> @$('li#page_' + exp + '_input').hide() + _.each options.features, (exp) -> @$("li##{model_name}_#{exp}_input").hide() options.on_callback() if options.on_callback? @_hide_last_separator() off_callback: => - _.each options.features, (exp) -> @$('li#page_' + exp + '_input').show() + _.each options.features, (exp) -> @$("li##{model_name}_#{exp}_input").show() options.off_callback() if options.off_callback? @_hide_last_separator() diff --git a/app/assets/stylesheets/locomotive/formtastic_changes.scss b/app/assets/stylesheets/locomotive/formtastic_changes.scss index 5fbaa498..1f20b4be 100644 --- a/app/assets/stylesheets/locomotive/formtastic_changes.scss +++ b/app/assets/stylesheets/locomotive/formtastic_changes.scss @@ -307,7 +307,27 @@ form.formtastic { background: transparent image-url("locomotive/icons/asset_add.png") no-repeat left 1px; } } + } // .more + + &.small { + + > textarea, .CodeMirror, .CodeMirror-scroll { + height: 60px; + width: 706px; + } + + .CodeMirror { + float: left; + margin-top: 0px; + margin-bottom: 5px; + } + + div.inline-errors, p.inline-hints { + margin-left: 160px; + } + } + } // li.code &.subdomain { @@ -440,7 +460,7 @@ form.formtastic { &#custom_fields_input { - padding-top: 10px; + padding-top: 17px; li.custom-field { height: auto; @@ -454,6 +474,7 @@ form.formtastic { position: relative; top: 3px; margin-left: 5px; + cursor: move; } span.label-input { diff --git a/app/controllers/locomotive/content_types_controller.rb b/app/controllers/locomotive/content_types_controller.rb index 9065eaa3..ada326de 100644 --- a/app/controllers/locomotive/content_types_controller.rb +++ b/app/controllers/locomotive/content_types_controller.rb @@ -5,7 +5,7 @@ module Locomotive respond_to :json, :only => [:create, :update, :destroy] - helper 'Locomotive::CustomFields' + helper 'Locomotive::Accounts', 'Locomotive::CustomFields' def new @content_type = current_site.content_types.new diff --git a/app/helpers/locomotive/accounts_helper.rb b/app/helpers/locomotive/accounts_helper.rb index 0ebf4c86..a6d05109 100644 --- a/app/helpers/locomotive/accounts_helper.rb +++ b/app/helpers/locomotive/accounts_helper.rb @@ -4,5 +4,9 @@ module Locomotive::AccountsHelper site.memberships.detect { |m| m.admin? && m.account == current_locomotive_account } end + def options_for_account + current_site.accounts.collect { |a| ["#{a.name} <#{a.email}>", a.id] } + end + end diff --git a/app/helpers/locomotive/custom_fields_helper.rb b/app/helpers/locomotive/custom_fields_helper.rb index 0044ebca..0239c976 100644 --- a/app/helpers/locomotive/custom_fields_helper.rb +++ b/app/helpers/locomotive/custom_fields_helper.rb @@ -1,17 +1,32 @@ module Locomotive::CustomFieldsHelper def options_for_custom_field_type - # %w(string text category boolean date file has_one has_many).map do |kind| - %w(string text category boolean date file).map do |type| + %w(string text select boolean date file).map do |type| [t("custom_fields.kind.#{type}"), type] end end - def options_for_order_by(content_type, collection_name) + def options_for_highlighted_field(content_type) + content_type.ordered_contents_custom_fields.find_all do |field| + %w(string date select).include?(field.type) + end.map do |field| + [field.label, field._id] + end + end + + def options_for_group_by_field(content_type) + content_type.ordered_contents_custom_fields.find_all do |field| + %w(select).include?(field.type) + end.map do |field| + [field.label, field._id] + end + end + + def options_for_order_by(content_type) options = %w{created_at updated_at _position_in_list}.map do |type| [t("locomotive.content_types.form.order_by.#{type.gsub(/^_/, '')}"), type] end - options + options_for_highlighted_field(content_type, collection_name) + options + options_for_highlighted_field(content_type) end def options_for_order_direction @@ -20,123 +35,109 @@ module Locomotive::CustomFieldsHelper end end - def options_for_highlighted_field(content_type, collection_name) - custom_fields_collection_name = "ordered_#{collection_name.singularize}_custom_fields".to_sym - collection = content_type.send(custom_fields_collection_name) - collection.delete_if { |f| f.label == 'field name' || %w(file has_one has_many).include?(f.kind) } - collection.map { |field| [field.label, field._name] } - end + # def options_for_text_formatting + # options = %w(none html).map do |option| + # [t("locomotive.custom_fields.text_formatting.#{option}"), option] + # end + # end - def options_for_group_by_field(content_type, collection_name) - custom_fields_collection_name = "ordered_#{collection_name.singularize}_custom_fields".to_sym - collection = content_type.send(custom_fields_collection_name) - collection.delete_if { |f| not f.category? } - collection.map { |field| [field.label, field._name] } - end - - def options_for_text_formatting - options = %w(none html).map do |option| - [t("locomotive.custom_fields.text_formatting.#{option}"), option] - end - end - - def options_for_association_target - current_site.reload.content_types.collect { |c| [c.name, c.content_klass.to_s] } - end - - def options_for_reverse_lookups(my_content_type) - klass_name = my_content_type.content_klass.to_s - - [].tap do |options| - ContentType.where(:'contents_custom_fields.kind' => 'has_one', :'contents_custom_fields.target' => klass_name).each do |content_type| - content_type.contents_custom_fields.find_all { |f| f.has_one? && f.target == klass_name }.each do |field| - options << { - :klass => content_type.content_klass.to_s, - :label => field.label, - :name => field._name - } - end - end - end - end - - def filter_options_for_reverse_has_many(contents, reverse_lookup, object) - # Only display items which don't belong to a different object - contents.reject do |c| - owner = c.send(reverse_lookup.to_sym) - !(owner.nil? || owner == object._id) - end - end - - def options_for_has_one(field, value) - self.options_for_has_one_or_has_many(field) do |groups| - grouped_options_for_select(groups.collect do |g| - if g[:items].empty? - nil - else - [g[:name], g[:items].collect { |c| [c._label, c._id] }] - end - end.compact, value) - end - end - - def options_for_has_many(field, content = nil) - self.options_for_has_one_or_has_many(field, content) - end - - def options_for_has_one_or_has_many(field, content = nil, &block) - content_type = field.target.constantize._parent.reload - - if content_type.groupable? - grouped_contents = content_type.list_or_group_contents - - grouped_contents.each do |g| - g[:items] = filter_options_for_reverse_has_many(g[:items], field.reverse_lookup, content) - end if field.reverse_has_many? - - if block_given? - block.call(grouped_contents) - else - grouped_contents.collect do |g| - if g[:items].empty? - nil - else - { :name => g[:name], :items => g[:items].collect { |c| [c._label, c._id] } } - end - end.compact - end - else - contents = content_type.ordered_contents - - if field.reverse_has_many? - contents = filter_options_for_reverse_has_many(contents, field.reverse_lookup, content) - end - - contents.collect { |c| [c._label, c._id] } - end - end - - def has_many_data_to_js(field, content) - options = { - :taken_ids => content.send(field._alias.to_sym).ids - } - - if !content.new_record? && field.reverse_has_many? - url_options = { - :breadcrumb_alias => field.reverse_lookup_alias, - "content[#{field.reverse_lookup_alias}]" => content._id - } - - options.merge!( - :new_item => { - :label => t('locomotive.contents.form.has_many.new_item'), - :url => new_content_url(field.target_klass._parent.slug, url_options) - }, - :edit_item_url => edit_content_url(field.target_klass._parent.slug, 42, url_options) - ) - end - - collection_to_js(options_for_has_many(field, content), options) - end + # def options_for_association_target + # current_site.reload.content_types.collect { |c| [c.name, c.content_klass.to_s] } + # end + # + # def options_for_reverse_lookups(my_content_type) + # klass_name = my_content_type.content_klass.to_s + # + # [].tap do |options| + # ContentType.where(:'contents_custom_fields.kind' => 'has_one', :'contents_custom_fields.target' => klass_name).each do |content_type| + # content_type.contents_custom_fields.find_all { |f| f.has_one? && f.target == klass_name }.each do |field| + # options << { + # :klass => content_type.content_klass.to_s, + # :label => field.label, + # :name => field._name + # } + # end + # end + # end + # end + # + # def filter_options_for_reverse_has_many(contents, reverse_lookup, object) + # # Only display items which don't belong to a different object + # contents.reject do |c| + # owner = c.send(reverse_lookup.to_sym) + # !(owner.nil? || owner == object._id) + # end + # end + # + # def options_for_has_one(field, value) + # self.options_for_has_one_or_has_many(field) do |groups| + # grouped_options_for_select(groups.collect do |g| + # if g[:items].empty? + # nil + # else + # [g[:name], g[:items].collect { |c| [c._label, c._id] }] + # end + # end.compact, value) + # end + # end + # + # def options_for_has_many(field, content = nil) + # self.options_for_has_one_or_has_many(field, content) + # end + # + # def options_for_has_one_or_has_many(field, content = nil, &block) + # content_type = field.target.constantize._parent.reload + # + # if content_type.groupable? + # grouped_contents = content_type.list_or_group_contents + # + # grouped_contents.each do |g| + # g[:items] = filter_options_for_reverse_has_many(g[:items], field.reverse_lookup, content) + # end if field.reverse_has_many? + # + # if block_given? + # block.call(grouped_contents) + # else + # grouped_contents.collect do |g| + # if g[:items].empty? + # nil + # else + # { :name => g[:name], :items => g[:items].collect { |c| [c._label, c._id] } } + # end + # end.compact + # end + # else + # contents = content_type.ordered_contents + # + # if field.reverse_has_many? + # contents = filter_options_for_reverse_has_many(contents, field.reverse_lookup, content) + # end + # + # contents.collect { |c| [c._label, c._id] } + # end + # end + # + # def has_many_data_to_js(field, content) + # options = { + # :taken_ids => content.send(field._alias.to_sym).ids + # } + # + # if !content.new_record? && field.reverse_has_many? + # url_options = { + # :breadcrumb_alias => field.reverse_lookup_alias, + # "content[#{field.reverse_lookup_alias}]" => content._id + # } + # + # options.merge!( + # :new_item => { + # :label => t('locomotive.contents.form.has_many.new_item'), + # :url => new_content_url(field.target_klass._parent.slug, url_options) + # }, + # :edit_item_url => edit_content_url(field.target_klass._parent.slug, 42, url_options) + # ) + # end + # + # collection_to_js(options_for_has_many(field, content), options) + # end end diff --git a/app/inputs/locomotive/small_code_input.rb b/app/inputs/locomotive/small_code_input.rb new file mode 100644 index 00000000..3e10b05f --- /dev/null +++ b/app/inputs/locomotive/small_code_input.rb @@ -0,0 +1,22 @@ +module Locomotive + class SmallCodeInput < Formtastic::Inputs::TextInput + + def wrapper_html_options + super.tap do |opts| + opts[:class] += ' code small' + end + end + + def input_wrapping(&block) + template.content_tag(:li, + [template.capture(&block), error_html, error_anchor, hint_html].join("\n").html_safe, + wrapper_html_options + ) + end + + def error_anchor + template.content_tag(:span, '', :class => 'error-anchor') + end + + end +end \ No newline at end of file diff --git a/app/models/locomotive/content_type.rb b/app/models/locomotive/content_type.rb index 617e9d9b..cb1430ac 100644 --- a/app/models/locomotive/content_type.rb +++ b/app/models/locomotive/content_type.rb @@ -11,12 +11,12 @@ module Locomotive field :name field :description field :slug + field :highlighted_field_id, :type => BSON::ObjectId + field :group_by_field_id, :type => BSON::ObjectId field :order_by field :order_direction, :default => 'asc' - field :highlighted_field_name - field :group_by_field_name - field :api_enabled, :type => Boolean, :default => false - field :api_accounts, :type => Array + field :public_form_enabled, :type => Boolean, :default => false + field :public_form_accounts, :type => Array ## associations ## belongs_to :site, :class_name => 'Locomotive::Site' @@ -48,6 +48,14 @@ module Locomotive # self.group_by_field && group_by_field.category? # end + def highlighted_field + self.contents_custom_fields.find(self.highlighted_field_id) + end + + def group_by_field + self.contents_custom_fields.find(self.group_by_field_id) + end + def order_manually? self.order_by == '_position_in_list' end @@ -133,7 +141,7 @@ module Locomotive def set_default_values self.order_by ||= 'created_at' - self.highlighted_field_name ||= self.contents_custom_fields.first.name + self.highlighted_field_id ||= self.contents_custom_fields.first._id end def normalize_slug diff --git a/app/models/locomotive/extensions/content_type/item_template.rb b/app/models/locomotive/extensions/content_type/item_template.rb index 336f7afe..d1d1848f 100644 --- a/app/models/locomotive/extensions/content_type/item_template.rb +++ b/app/models/locomotive/extensions/content_type/item_template.rb @@ -40,7 +40,9 @@ module Locomotive end def item_template_must_be_valid - @item_parsing_errors.try(:each) { |msg| self.errors.add :item_template, msg } + @item_parsing_errors.try(:each) do |msg| + %w(item_template raw_item_template).each { |field| self.errors.add field.to_sym, msg } + end end end diff --git a/app/views/locomotive/content_types/_form.html.haml b/app/views/locomotive/content_types/_form.html.haml index 495c0fcb..ac40ab36 100644 --- a/app/views/locomotive/content_types/_form.html.haml +++ b/app/views/locomotive/content_types/_form.html.haml @@ -10,27 +10,18 @@ = f.input :slug = f.input :description -= f.inputs :name => :custom_fields, :class => "inputs foldable #{'folded' if inputs_folded?(@content_type)}" do += f.inputs :name => :custom_fields, :class => "inputs foldable" do = f.input :contents_custom_fields, :as => :'Locomotive::Empty', :label => false, :wrapper_html => { :id => 'custom_fields_input' } -/ = render 'locomotive/custom_fields/index', :form => f, :collection_name => 'contents' -/ -/ - unless f.object.new_record? -/ = f.foldable_inputs :name => :presentation, :class => 'switchable' do -/ = f.input :highlighted_field_name, :as => :select, :collection => options_for_highlighted_field(f.object, 'contents'), :include_blank => false -/ = f.input :group_by_field_name, :as => :select, :collection => options_for_group_by_field(f.object, 'contents') -/ = f.custom_input :item_template, :css => 'small-code' do -/ %code{ :class => 'html' } -/ = f.text_area :raw_item_template, :class => 'small' -/ -/ = f.foldable_inputs :name => :options, :class => 'switchable' do -/ = f.input :order_by, :as => :select, :collection => options_for_order_by(f.object, 'contents'), :include_blank => false -/ = f.input :order_direction, :as => :select, :collection => options_for_order_direction, :include_blank => false, :wrapper_html => { :style => "#{'display: none' if f.object.order_manually?}" } -/ = f.custom_input :api_enabled, :css => 'toggle' do -/ = f.check_box :api_enabled -/ = hidden_field_tag 'content_type[api_accounts][]', '' -/ = f.input :api_accounts, :as => :select, :collection => current_site.accounts.collect { |a| ["#{a.name} <#{a.email}>", a.id] }, :include_blank => false, :multiple => true, :wrapper_html => { :class => 'multiple', :style => (f.object.api_enabled? ? '' : 'display: none') } -/ -/ -/ -/ +- if @content_type.persisted? + + = f.inputs :name => :presentation, :class => "inputs foldable #{'folded' if inputs_folded?(@content_type)}" do + = f.input :highlighted_field_id, :as => :select, :collection => options_for_highlighted_field(@content_type), :include_blank => false + = f.input :group_by_field_id, :as => :select, :collection => options_for_group_by_field(@content_type) + = f.input :raw_item_template, :as => :'Locomotive::SmallCode' + + = f.inputs :name => :options, :class => "inputs foldable #{'folded' if inputs_folded?(@content_type)}" do + = f.input :order_by, :as => :select, :collection => options_for_order_by(@content_type), :include_blank => false + = 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_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') } diff --git a/config/locales/formtastic.en.yml b/config/locales/formtastic.en.yml index 42250584..160c955e 100644 --- a/config/locales/formtastic.en.yml +++ b/config/locales/formtastic.en.yml @@ -40,7 +40,7 @@ en: reset: Reset site default_site_template: "Use the default site template. Click here to upload a site template as a zip file instead." content_type: - item_template: Item template + raw_item_template: Item template api_accounts: Notified Accounts content_instance: _slug: Permalink @@ -91,11 +91,11 @@ en: reset: "If enabled, all the data of your site will be destroyed before importing the new site" content_type: 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 }}" - item_template: "You can customize the text displayed for each item in the list. Simply use Liquid. Ex: {{ content.name }})" - api_enabled: "It is used to let people from outside to create new instances (example: messages in a contact form)" - api_accounts: "A notification email will be sent to each of the accounts listed above when a new instance is created" + 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: {{ content.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" "custom_fields/field": - name: "Name of the property for liquid templates. Ex: {{ your_object.<name_of_your_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/doc/TODO b/doc/TODO index 8c79444b..4a6b9460 100644 --- a/doc/TODO +++ b/doc/TODO @@ -44,9 +44,11 @@ x edit my site x look n feel x display errors x slugify + x refactor highlighted_field (field id instead of name) - other content type options - show / hide options of a field based on its type - - refactor highlighted_field (field id instead of name) + - select: add/edit/remove options + - text: formatting - change in main menu - manage contents - list diff --git a/doc/changelogs/version_2.txt b/doc/changelogs/version_2.txt index 411695dc..c82b5b5d 100644 --- a/doc/changelogs/version_2.txt +++ b/doc/changelogs/version_2.txt @@ -4,4 +4,9 @@ - theme_assets.images => theme_assets.image_picker - assets => content_assets - - EditableXXX => Locomotive::EditableXXX (en mongodb) \ No newline at end of file + - EditableXXX => Locomotive::EditableXXX (in mongodb) + - content_types: + - category => select + - highlighted_field_name => highlighted_field_id + - api_enabled => public_form_enabled + - api_accounts => public_form_accounts \ No newline at end of file