add the ui element to select the languages for a site

This commit is contained in:
did 2012-01-09 17:24:34 -08:00
parent 4c204ef6a6
commit 01c5de36a5
19 changed files with 265 additions and 75 deletions

View File

@ -14,8 +14,6 @@ class Locomotive.Views.ContentEntries.FormView extends Locomotive.Views.Shared.F
initialize: -> initialize: ->
@model = new Locomotive.Models.ContentEntry(@options.content_entry) @model = new Locomotive.Models.ContentEntry(@options.content_entry)
console.log(@model.urlRoot)
window.foo = @model window.foo = @model
Backbone.ModelBinding.bind @ 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')) @$('li.input.highlighted > input[type=text]').slugify(target: @$('#content_entry__slug'))
refresh_file_fields: -> refresh_file_fields: ->
console.log('refresh_file_fields')
_.each @_file_field_views, (view) => view.refresh() _.each @_file_field_views, (view) => view.refresh()
remove: -> remove: ->

View File

@ -13,19 +13,39 @@ class Locomotive.Views.CurrentSite.EditView extends Locomotive.Views.Shared.Form
initialize: -> initialize: ->
@model = new Locomotive.Models.CurrentSite(@options.site) @model = new Locomotive.Models.CurrentSite(@options.site)
Backbone.ModelBinding.bind @ Backbone.ModelBinding.bind @, checkbox: 'class'
window.foo = @model window.foo = @model
render: -> render: ->
super() super()
@add_toggle_mode_for_locales()
@make_locales_sortable()
@render_domains() @render_domains()
@render_memberships() @render_memberships()
@enable_liquid_editing() @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: -> render_domains: ->
@domains_view = new Locomotive.Views.Sites.DomainsView model: @model, errors: @options.errors @domains_view = new Locomotive.Views.Sites.DomainsView model: @model, errors: @options.errors

View File

@ -17,7 +17,6 @@ class Locomotive.Views.Import.ShowView extends Backbone.View
@refresh_steps @refresh_steps
refresh_steps: (data) => refresh_steps: (data) =>
console.log 'refresh_steps: ....'
window.foo = data window.foo = data
window.bar = @ window.bar = @

View File

@ -279,6 +279,63 @@ form.formtastic {
} }
} // li.string, li.password } // 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 { &.code {
textarea, .CodeMirror-scroll { textarea, .CodeMirror-scroll {
@ -521,35 +578,6 @@ form.formtastic {
} }
} // > li#site_memberships_input } // > 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 { &#account_sites_input {
.entry { .entry {
strong { strong {

View File

@ -7,6 +7,8 @@ module Locomotive
load_and_authorize_resource :class => 'Site' load_and_authorize_resource :class => 'Site'
helper 'Locomotive::Sites'
before_filter :filter_attributes before_filter :filter_attributes
respond_to :json, :only => :update respond_to :json, :only => :update

View File

@ -1,11 +1,7 @@
module Locomotive::SitesHelper module Locomotive::SitesHelper
# def error_on_domain(site, name) def ordered_current_site_locales
# if (error = (site.errors[:domains] || []).detect { |n| n.include?(name) }) current_site.locales + (Locomotive.config.site_locales - current_site.locales)
# content_tag(:span, error, :class => 'inline-errors') end
# else
# ''
# end
# end
end end

View File

@ -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

View File

@ -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

View File

@ -7,6 +7,7 @@ module Locomotive
extend Extensions::Site::SubdomainDomains extend Extensions::Site::SubdomainDomains
extend Extensions::Site::FirstInstallation extend Extensions::Site::FirstInstallation
include Extensions::Shared::Seo include Extensions::Shared::Seo
include Extensions::Site::I18n
## fields ## ## fields ##
field :name field :name

View File

@ -1,7 +1,7 @@
module Locomotive module Locomotive
class SitePresenter < BasePresenter 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 def domain_name
Locomotive.config.domain Locomotive.config.domain
@ -12,7 +12,7 @@ module Locomotive
end end
def included_methods 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
end end

View File

@ -6,13 +6,9 @@
:plain :plain
{ site: #{@site.to_json(:current_account => current_locomotive_account, :current_site => current_site)}, errors: #{@site.errors.to_json} } { 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.inputs :name => :information do
= f.input :name = f.input :name, :wrapper_html => { :style => 'display: none' }
= f.input :locales, :as => '::Locomotive::Locales', :collection => ordered_current_site_locales, :input_html => { :class => 'locales' }
= 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?(:point, Locomotive::Site) - if can?(:point, Locomotive::Site)
- if manage_subdomain_or_domains? - if manage_subdomain_or_domains?
@ -22,6 +18,12 @@
- if manage_domains? - if manage_domains?
= f.input :domains, :as => :'Locomotive::Empty' = 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) - if can?(:index, Locomotive::Membership)
= f.inputs :name => :memberships do = f.inputs :name => :memberships do

View File

@ -54,6 +54,8 @@ en:
password_confirmation: New password confirmation password_confirmation: New password confirmation
page: page:
seo_title: Title seo_title: Title
site:
locales: Languages
hints: hints:
page: page:
@ -68,6 +70,7 @@ en:
snippet: snippet:
slug: "You need to know it in order to insert the snippet inside a page" slug: "You need to know it in order to insert the snippet inside a page"
site: 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." 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_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." meta_description: "Meta description used within the head tag of the page. Required for SEO."

View File

@ -66,6 +66,10 @@ x edit my site
- use list_or_group_entries instead of ordered_entries - use list_or_group_entries instead of ordered_entries
- bug ui with contents popup - bug ui with contents popup
- custom_fields: use the appropriate icon to drag select options - 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 ?) - disallow to click twice on the submit form button (spinner ?)
- message to notify people if their browser is too old - message to notify people if their browser is too old

View File

@ -52,6 +52,9 @@ Locomotive.configure do |config|
# default locale (for now, only en, de, fr, pt-BR and it are supported) # default locale (for now, only en, de, fr, pt-BR and it are supported)
config.default_locale = :en 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. # tell if logs are enabled. Useful for debug purpose.
config.enable_logs = true config.enable_logs = true

View File

@ -8,6 +8,7 @@ module Locomotive
# :forbidden_paths => %w{layouts snippets stylesheets javascripts assets admin system api}, # :forbidden_paths => %w{layouts snippets stylesheets javascripts assets admin system api},
:reserved_slugs => %w{stylesheets javascripts assets admin images api pages edit}, :reserved_slugs => %w{stylesheets javascripts assets admin images api pages edit},
:locales => %w{en de fr pt-BR it nl no es ru}, :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', :cookie_key => '_locomotive_session',
:enable_logs => false, :enable_logs => false,
:hosting => :auto, :hosting => :auto,

View File

@ -2,32 +2,33 @@
require 'mongoid' require 'mongoid'
module Mongoid module Mongoid#:nodoc:
module Document module Document #:nodoc:
def as_json(options = {}) def as_json(options = {})
attrs = super(options) attrs = super(options)
attrs["id"] = attrs["_id"] attrs["id"] = attrs["_id"]
attrs attrs
end end
end end
module Fields #:nodoc:
module Internal #:nodoc:
class RawArray < Mongoid::Fields::Internal::Array
def resizable?; false; end
end
end end
# Limit feature for embedded documents class RawArray < ::Array; end
end
module Mongoid #:nodoc:
# without callback feature # without callback feature
module Callbacks module Callbacks #:nodoc:
module ClassMethods #:nodoc:
module ClassMethods
def without_callback(*args, &block) def without_callback(*args, &block)
skip_callback(*args) skip_callback(*args)
yield yield
set_callback(*args) set_callback(*args)
end end
end
end
end end
end end

View File

@ -53,6 +53,9 @@ Locomotive.configure do |config|
# default locale (for now, only en, de, fr, pt-BR and it are supported) # default locale (for now, only en, de, fr, pt-BR and it are supported)
config.default_locale = :en 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. # tell if logs are enabled. Useful for debug purpose.
config.enable_logs = true config.enable_logs = true

View File

@ -364,26 +364,39 @@ Backbone.ModelBinding = (function(Backbone, _, $){
} }
// console.log(attribute_name); // console.log(attribute_name);
var isArray = _.isArray(model.get(attribute_name))
var modelChange = function(model, val){ var modelChange = function(model, val){
if (val){ var checked = val;
if (isArray)
checked = _.include(val, element.val());
if (checked)
element.attr("checked", "checked"); element.attr("checked", "checked");
} else
else{
element.removeAttr("checked"); element.removeAttr("checked");
}
}; };
var setModelValue = function(attr_name, value){ var setModelValue = function(attr_name, checked, value){
var data = {}; var data = {};
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; data[attr_name] = value;
model.set(data); model.set(data);
}; };
var elementChange = function(ev){ var elementChange = function(ev){
// console.log('[SELECT] elementChange'); // console.log('[CHECKBOX] elementChange');
var changedElement = view.$(ev.target); var changedElement = view.$(ev.target);
var checked = changedElement.is(":checked")? true : false; var checked = changedElement.is(":checked")? true : false;
setModelValue(attribute_name, checked); setModelValue(attribute_name, checked, changedElement.val());
}; };
modelBinder.registerModelBinding(model, attribute_name, modelChange); modelBinder.registerModelBinding(model, attribute_name, modelChange);
@ -393,16 +406,16 @@ Backbone.ModelBinding = (function(Backbone, _, $){
if (attr_exists) { if (attr_exists) {
// set the default value on the form, from the model // set the default value on the form, from the model
var attr_value = model.get(attribute_name); 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"); element.attr("checked", "checked");
} }else{
else{
element.removeAttr("checked"); element.removeAttr("checked");
} }
} else { } else {
// bind the form's value to the model // bind the form's value to the model
var checked = element.is(":checked")? true : false; var checked = element.is(":checked")? true : false;
setModelValue(attribute_name, checked); setModelValue(attribute_name, checked, element.val());
} }
}); });
}; };

View File

@ -51,6 +51,11 @@
var _buildParams = function(prefix, obj, fn) { // code grabbed from jquery var _buildParams = function(prefix, obj, fn) { // code grabbed from jquery
if (jQuery.isArray(obj)) { if (jQuery.isArray(obj)) {
if (obj.length == 0) { // empty arrays
fn(prefix, obj);
return;
}
jQuery.each(obj, function(i, v) { jQuery.each(obj, function(i, v) {
if (/\[\]$/.test(prefix)) { // rbracket if (/\[\]$/.test(prefix)) { // rbracket
fn(prefix, v); fn(prefix, v);