it is now possible to change the response type of a page + correct translations in French

This commit is contained in:
Didier Lafforgue 2012-03-22 19:20:31 +01:00
parent 6b8e3db8c3
commit a9aeffba9b
15 changed files with 126 additions and 50 deletions

View File

@ -16,7 +16,7 @@ class Locomotive.Models.Page extends Backbone.Model
toJSON: ->
_.tap super, (hash) =>
_.each ['content_type_id_text', 'edit_url', 'parent_id_text'], (key) => delete hash[key]
_.each ['content_type_id_text', 'edit_url', 'parent_id_text', 'response_type_text'], (key) => delete hash[key]
delete hash['editable_elements']
hash.editable_elements = @get('editable_elements').toJSONForSave() if @get('editable_elements')? && @get('editable_elements').length > 0

View File

@ -37,6 +37,9 @@ class Locomotive.Views.Pages.FormView extends Locomotive.Views.Shared.FormView
# the url gets modified by different ways so reflect the changes in the UI
@listen_for_url_changes()
# enable response type
@enable_response_type_select()
# enable check boxes
@enable_templatized_checkbox()
@ -110,6 +113,14 @@ class Locomotive.Views.Pages.FormView extends Locomotive.Views.Shared.FormView
success: (data) =>
@$('#page_slug_input .inline-hints').html(data.url).effect('highlight')
enable_response_type_select: ->
@$('li#page_response_type_input').change (event) =>
if $(event.target).val() == 'text/html'
@$('li#page_redirect_input, li#page_redirect_url_input').show()
else
@model.set redirect: false
@$('li#page_redirect_input, li#page_redirect_url_input').hide()
enable_templatized_checkbox: ->
@_enable_checkbox 'templatized',
features: ['slug', 'redirect', 'listed']

View File

@ -80,6 +80,7 @@ ul.list {
span.untranslated {
@include label;
background-color: #F89406;
top: -1px;
left: 5px;
}
@ -219,6 +220,13 @@ ul.list {
&.hidden a { font-style: italic; font-weight: normal; }
span.untranslated {
@include label;
background-color: #F89406;
top: 3px;
left: 5px;
}
span.response-type {
@include label;
top: 3px;
left: 5px;

View File

@ -50,5 +50,18 @@ module Locomotive
]
end
def options_for_page_response_type
[
['HTML', 'text/html'],
['RSS', 'application/rss+xml'],
['XML', 'text/xml'],
['JSON', 'application/json']
]
end
def page_response_type_to_string(page)
options_for_page_response_type.detect { |t| t.last == page.response_type }.try(:first) || '—'
end
end
end

View File

@ -22,6 +22,7 @@ module Locomotive
field :locales, :type => Array
field :published, :type => Boolean, :default => false
field :cache_strategy, :default => 'none'
field :response_type, :default => 'text/html'
## associations ##
belongs_to :site, :class_name => 'Locomotive::Site'
@ -51,7 +52,7 @@ module Locomotive
scope :published, :where => { :published => true }
scope :fullpath, lambda { |fullpath| { :where => { :fullpath => fullpath } } }
scope :handle, lambda { |handle| { :where => { :handle => handle } } }
scope :minimal_attributes, lambda { |attrs = []| { :only => (attrs || []) + %w(title slug fullpath position depth published templatized redirect listed parent_id site_id created_at updated_at) } }
scope :minimal_attributes, lambda { |attrs = []| { :only => (attrs || []) + %w(title slug fullpath position depth published templatized redirect listed response_type parent_id site_id created_at updated_at) } }
scope :dependent_from, lambda { |id| { :where => { :template_dependencies.in => [id] } } }
## methods ##
@ -72,6 +73,10 @@ module Locomotive
self.cache_strategy != 'none'
end
def default_response_type?
self.response_type == 'text/html'
end
def translated?
self.title_translations.key?(::Mongoid::Fields::I18n.locale.to_s) rescue false
end

View File

@ -1,7 +1,7 @@
module Locomotive
class PagePresenter < BasePresenter
delegate :title, :slug, :fullpath, :handle, :raw_template, :published, :listed, :templatized, :redirect, :redirect_url, :template_changed, :cache_strategy, :to => :source
delegate :title, :slug, :fullpath, :handle, :raw_template, :published, :listed, :templatized, :redirect, :redirect_url, :template_changed, :cache_strategy, :response_type, :to => :source
def escaped_raw_template
h(self.source.raw_template)
@ -12,7 +12,7 @@ module Locomotive
end
def included_methods
super + %w(title slug fullpath handle raw_template published listed templatized redirect redirect_url cache_strategy template_changed editable_elements localized_fullpaths)
super + %w(title slug fullpath handle raw_template published listed templatized redirect redirect_url cache_strategy response_type template_changed editable_elements localized_fullpaths)
end
def localized_fullpaths

View File

@ -32,6 +32,8 @@
= f.input :handle
= f.input :response_type, :as => :select, :collection => options_for_page_response_type, :include_blank => false
= f.input :templatized, :as => :'Locomotive::Toggle', :style => "#{'display: none' if @page.redirect?}"
= f.input :target_klass_name, :as => :select, :collection => options_for_target_klass_name, :include_blank => false, :wrapper_html => { :style => "#{'display: none' unless @page.templatized?}" }
@ -40,7 +42,7 @@
= f.input :listed, :as => :'Locomotive::Toggle'
= f.input :redirect, :as => :'Locomotive::Toggle', :style => "#{'display: none' if @page.templatized?}"
= f.input :redirect, :as => :'Locomotive::Toggle', :wrapper_html => { :style => "#{'display: none' if @page.templatized? || !@page.default_response_type?}" }
= f.input :cache_strategy, :as => :select, :collection => options_for_page_cache_strategy, :include_blank => false, :wrapper_html => { :style => "#{'display: none' if @page.redirect?}" }

View File

@ -17,6 +17,9 @@
= link_to truncate(page.title, :length => 80), edit_page_url(page)
- unless page.default_response_type?
%span.response-type= page_response_type_to_string(page)
- unless page.translated?
%span.untranslated= t('locomotive.shared.list.untranslated')

View File

@ -77,10 +77,17 @@ fr:
file:
delete_file: Supprimer fichier
has_many:
empty: Vide
empty: La liste est vide
new_entry: + Ajouter une nouvelle entrée
many_to_many:
empty: La liste est vide. Ajouter une entrée depuis la liste ci-dessous.
form:
is_required: est obligatoire
default_label: Nom du champ
required: Required
optional: Optional
default_label: Field name
select_options:
ask_name: "Type the label of the option"
sessions:
new:
@ -149,6 +156,8 @@ fr:
new:
title: "Nouveau site"
help: "Remplissez le formulaire ci-dessous pour créer votre nouveau site."
domains:
empty: Aucun domaine
current_site:
edit:
@ -187,6 +196,7 @@ fr:
media: Média
fonts: Polices
no_items: "Il n'existe pas de fichiers."
quick_upload: "Upload rapide"
asset:
updated_at: Mis à jour le
new:
@ -216,6 +226,7 @@ fr:
content_types:
index:
new: nouveau modèle
edit: éditer
new:
title: Nouveau modèle
help: "Créer votre propre modèle de données (Projets, Personnes, ...etc). Votre modèle doit au moins comporter un champ. Le premier champ sera obligatoire lorsque vous ajouterez un élément de ce type-là."

View File

@ -52,7 +52,7 @@ fr:
mongoid:
attributes:
page:
locomotive/page:
title: Titre
parent: Dossier parent
parent_id: Dossier parent
@ -63,42 +63,49 @@ fr:
redirect: Redirection
redirect_url: Url de redirection
cache_strategy: Cache
response_type: Type de réponse
seo_title: Titre SEO
content_type:
locomotive/content_type:
name: Nom
description: Description
slug: Raccourci
order_by: Ordonner
highlighted_field_name: Champ mis en avant
order_direction: Direction
label_field_name: Champ mis en avant
label_field_id: Champ mis en avant
group_by_field_name: Champ pour grouper
api_enabled: Activation API
asset:
group_by_field_id: Champ pour grouper
public_submission_enabled: Activation API
public_submission_accounts: Comptes à notifier
locomotive/asset:
source: Fichier
account:
locomotive/account:
email: E-mail
name: Nom
language: Langue
password: Mot de passe
password_confirmation: Confirmation mot de passe
snippet:
locomotive/snippet:
body: Code
slug: Raccourci
name: Nom
theme_asset:
locomotive/theme_asset:
content_type: Type du fichier
site:
locomotive/site:
name: Nom du site
locales: Langues
domain_name: Domaine
subdomain: Sous-domaine
restricted_access: Activer ?
access_login: Identifiant
access_password: "Mot de passe"
custom_fields:
field:
name: Alias
hint: Aide
required: Requis ?
text_formatting: Formattage
custom_fields/field:
name: Alias
hint: Aide
required: Requis ?
text_formatting: Formattage
localized: Localisé ?
select_options: Options
pagination:
previous: "&laquo; Précédent"

View File

@ -33,12 +33,6 @@ en:
custom_fields:
field:
name: Alias
import:
new:
source: File
samples: Copy samples
reset: Reset site
default_site_template: "Use the default site template. Click <a href='#'>here</a> to upload a site template as a zip file instead."
content_type:
raw_item_template: Item template
public_submission_enabled: Public submission

View File

@ -35,13 +35,8 @@ fr:
custom_fields:
field:
name: Alias
import:
new:
source: Fichier
samples: Copier contenu
reset: Remettre à zéro
content_type:
item_template: Template d'affichage
raw_item_template: Template d'affichage
api_accounts: Comptes à notifier
content_entry:
_slug: Permalink
@ -51,6 +46,7 @@ fr:
password: Nouveau mot de passe
password_confirmation: Confirmation nouveau mot de passe
page:
target_klass_name: Modèle
seo_title: Titre
hints:
@ -59,13 +55,14 @@ fr:
cache_strategy: "Cache la page pour de meilleure performance. L'option 'Simple' est le meilleur compromis."
templatized: "Utilise la page comme un template pour un modèle défini."
listed: "Controle si la page doit être visible depuis les menus automatiquement générés."
content_type_id: "Le type du contenu pour lequel cette page est un template."
target_klass_name: "Le type du contenu pour lequel cette page est un template."
seo_title: "Définit un titre de page à mettre dans la balise TITLE de la page. Laissez le blanc pour utiliser la valeur par défaut (voir configuration du site)."
meta_keywords: "Redéfinit les mots-clés du site. Utilisés à l'intérieur de la balise HEAD. Ils sont séparés par une virgule."
meta_description: "Redéfinit la description du site. Utilisée à l'intérieur de la balise HEAD."
snippet:
slug: "Utilisé pour insérer le snippet dans une page."
site:
seo_title: "Valeur globale qui sera utilisée par défaut dans la balise TITLE de la section HEAD. Requis pour un meilleur référencement."
meta_keywords: "Mots-clés utilisés à l'intérieur de la balise HEAD. Ils sont séparés par une virgule. Requis pour un meilleur référencement."
meta_description: "Description utilisée à l'intérieur de la balise HEAD. Requis pour un meilleur référencement."
domain_name: "ex: locomotiveapp.org"
@ -88,12 +85,8 @@ fr:
seo_title: "La valeur que vous rentrez sera utilisée comme titre SEO pour la page faisant office de template pour ce modèle."
meta_keywords: "Redéfinit les mots-clés du site. Utilisés à l'intérieur de la balise HEAD. Ils sont séparés par une virgule."
meta_description: "Redéfinit la description du site. Utilisée à l'intérieur de la balise HEAD."
import:
source: "Un fichier zip contenant database.yml, les fichiers du thème et les templates de page"
samples: "Si activé, les contenus et les média seront aussi copiés lors de l'import"
reset: "Si activé, toutes les données de votre site seront détruites avant l'import du nouveau site"
content_type:
slug: Nom utilisé dans les templates liquid afin d'accéder aux enregistrements de ce modèle
item_template: "Personnaliser le texte affiché pour chaque élément de la liste. Utilisez simplement du code Liquid. Ex: {{ entry.name }}"
api_enabled: "Utilisé pour autoriser la création de nouvelles instances de l'extérieur (ex.: les messages dans un formulaire de contact)"
api_accounts: "Un email de notification sera envoyé à chaque compte listé ci-dessus lors de la création d'une nouvelle instance"
raw_item_template: "Personnaliser le texte affiché pour chaque élément de la liste. Utilisez simplement du code Liquid. Ex: {{ entry.name }}"
public_submission_enabled: "Utilisé pour autoriser la création de nouvelles instances de l'extérieur (ex.: les messages dans un formulaire de contact)"
public_submission_accounts: "Un email de notification sera envoyé à chaque compte listé ci-dessus lors de la création d'une nouvelle instance"

View File

@ -26,20 +26,25 @@ module Locomotive
end
def locomotive_page
page = nil
path = self.locomotive_page_path
if page = current_site.pages.any_in(:fullpath => [*path]).first
if not page.published? and current_locomotive_account.nil?
page = nil
current_site.pages.any_in(:fullpath => [*path]).each do |_page|
if not _page.published? and current_locomotive_account.nil?
next
else
if page.templatized?
@content_entry = page.fetch_target_entry(File.basename(path.first))
if _page.templatized?
@content_entry = _page.fetch_target_entry(File.basename(path.first))
if @content_entry.nil? || (!@content_entry.visible? && current_locomotive_account.nil?) # content instance not found or not visible
page = nil
next
end
end
end
page = _page
break
end
page || not_found_page
@ -101,7 +106,7 @@ module Locomotive
def prepare_and_set_response(output)
flash.discard
response.headers['Content-Type'] = 'text/html; charset=utf-8'
response.headers['Content-Type'] = "#{@page.response_type}; charset=utf-8"
response.headers['Editable'] = 'true' unless self.editing_page? || current_locomotive_account.nil?
if @page.with_cache?

View File

@ -37,6 +37,12 @@ describe 'Locomotive rendering system' do
@controller.response.headers['Content-Type'].should == 'text/html; charset=utf-8'
end
it 'sets the content type to the one specified by the page' do
@page.response_type = 'application/json'
@controller.send(:prepare_and_set_response, 'Hello world !')
@controller.response.headers['Content-Type'].should == 'application/json; charset=utf-8'
end
it 'sets the status to 200 OK' do
@controller.status.should == :ok
end

View File

@ -307,6 +307,24 @@ describe Locomotive::Page do
end
end
describe 'response type' do
before(:each) do
@page = FactoryGirl.build(:page, :site => nil)
end
it 'is a HTML document by default' do
@page.response_type.should == 'text/html'
@page.default_response_type?.should be_true
end
it 'can also be a JSON document' do
@page.response_type = 'application/json'
@page.default_response_type?.should be_false
end
end
class Foo
end