make the edition of content types more robust (ex: better errors handler)

This commit is contained in:
did 2012-01-18 01:43:01 +01:00
parent 09d6060633
commit b8b8cef089
15 changed files with 90 additions and 62 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 356 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 359 B

View File

@ -14,7 +14,7 @@ class Locomotive.Models.ContentType extends Backbone.Model
toJSON: -> toJSON: ->
_.tap super, (hash) => _.tap super, (hash) =>
delete hash.entries_custom_fields delete hash.entries_custom_fields
hash.entries_custom_fields_attributes = @get('entries_custom_fields').toJSONForSave() if @get('entries_custom_fields') hash.entries_custom_fields_attributes = @get('entries_custom_fields').toJSONForSave() if @get('entries_custom_fields')? && @get('entries_custom_fields').length > 0
class Locomotive.Models.ContentTypesCollection extends Backbone.Collection class Locomotive.Models.ContentTypesCollection extends Backbone.Collection

View File

@ -12,8 +12,6 @@ class Locomotive.Views.ContentTypes.FormView extends Locomotive.Views.Shared.For
initialize: -> initialize: ->
@model = new Locomotive.Models.ContentType(@options.content_type) @model = new Locomotive.Models.ContentType(@options.content_type)
window.foo = @model
Backbone.ModelBinding.bind @ Backbone.ModelBinding.bind @
render: -> render: ->
@ -64,12 +62,20 @@ class Locomotive.Views.ContentTypes.FormView extends Locomotive.Views.Shared.For
target.show() target.show()
show_error: (attribute, message, html) -> show_error: (attribute, message, html) ->
if attribute == 'entries_custom_fields' if attribute != 'entries_custom_fields'
return if _.isEmpty(message)
for _message, index in message
@custom_fields_view._entry_views[index].show_error(_message[0])
else
super super
else
return if _.isEmpty(message)
_.each _.keys(message), (key) =>
_messages = message[key]
if key == 'base'
html = $("<div class=\"inline-errors\"><p>#{_messages[0]}</p></div>")
@$('#custom_fields_input .list').after(html)
else
view = @custom_fields_view.find_entry_view(key)
view.show_error(_messages[0]) if view?
remove: -> remove: ->
@custom_fields_view.remove() @custom_fields_view.remove()

View File

@ -28,6 +28,8 @@ class Locomotive.Views.ContentTypes.CustomFieldEntryView extends Backbone.View
return @ return @
enable_behaviours: -> enable_behaviours: ->
required_input = @$('.required-input input[type=checkbox]')
required_input.checkToggle(on_label: required_input.attr('data-on-label'), off_label: required_input.attr('data-off-label'))
@$('li.input.toggle input[type=checkbox]').checkToggle() @$('li.input.toggle input[type=checkbox]').checkToggle()
@render_select_options_view() @render_select_options_view()
@ -48,7 +50,7 @@ class Locomotive.Views.ContentTypes.CustomFieldEntryView extends Backbone.View
@$('#content_type_contents_custom_field_select_options_input').append(@select_options_view.render().el) @$('#content_type_contents_custom_field_select_options_input').append(@select_options_view.render().el)
make_fields_editable: -> make_fields_editable: ->
@$('span.label-input input[type=text], span.type-input select').editableField() @$('.label-input input[type=text], .type-input select').editableField()
toggle: (event) -> toggle: (event) ->
event.stopPropagation() & event.preventDefault() event.stopPropagation() & event.preventDefault()
@ -60,13 +62,13 @@ class Locomotive.Views.ContentTypes.CustomFieldEntryView extends Backbone.View
form.slideUp() form.slideUp()
show_error: (message) -> show_error: (message) ->
html = $("<span class=\"inline-errors\">#{message}</div>") html = $("<span class=\"inline-errors\">#{message}</span>")
@$('span.required-input').after(html) @$('.required-input').after(html)
remove: (event) -> remove: (event) ->
event.stopPropagation() & event.preventDefault() event.stopPropagation() & event.preventDefault()
if confirm($(event.target).attr('data-confirm')) if confirm($(event.target).attr('data-confirm'))
@$('span.label-input input[type=text], span.type-input select').editableField('destroy') @$('.label-input input[type=text], .type-input select').editableField('destroy')
super() super()
@options.parent_view.remove_entry(@model, @) @options.parent_view.remove_entry(@model, @)

View File

@ -26,7 +26,7 @@ class Locomotive.Views.ContentTypes.CustomFieldsView extends Backbone.View
make_list_sortable: -> make_list_sortable: ->
@sortable_list = @$('> ul').sortable @sortable_list = @$('> ul').sortable
handle: 'span.handle' handle: '.handle'
items: 'li.custom-field' items: 'li.custom-field'
axis: 'y' axis: 'y'
update: @refresh_position_entries update: @refresh_position_entries
@ -35,6 +35,13 @@ class Locomotive.Views.ContentTypes.CustomFieldsView extends Backbone.View
_.each @_entry_views, (view) -> _.each @_entry_views, (view) ->
view.model.set position: $(view.el).index() view.model.set position: $(view.el).index()
find_entry_view: (key) ->
_.find @_entry_views, (view) ->
if key.length > 3
view.model.id == key
else
view.model.get('position') == parseInt(key)
add_entry: (event) -> add_entry: (event) ->
event.stopPropagation() & event.preventDefault() event.stopPropagation() & event.preventDefault()

View File

@ -75,11 +75,11 @@ class Locomotive.Views.Shared.FormView extends Backbone.View
show_errors: (errors) -> show_errors: (errors) ->
for attribute, message of errors for attribute, message of errors
if _.isArray(message[0]) if _.isString(message[0])
@show_error attribute, message
else
html = $("<div class=\"inline-errors\"><p>#{message[0]}</p></div>") html = $("<div class=\"inline-errors\"><p>#{message[0]}</p></div>")
@show_error attribute, message[0], html @show_error attribute, message[0], html
else
@show_error attribute, message
show_error: (attribute, message, html) -> show_error: (attribute, message, html) ->
input = @$("##{@model.paramRoot}_#{attribute}") input = @$("##{@model.paramRoot}_#{attribute}")

View File

@ -12,6 +12,16 @@ form.formtastic {
padding-bottom: 1px; padding-bottom: 1px;
span.inline-errors {
margin-left: 10px;
padding: 2px 3px;
background: #FFE5E5;
color: #CE2525;
font-size: 13px;
}
legend { legend {
display: block; display: block;
width: 918px; width: 918px;
@ -101,16 +111,6 @@ form.formtastic {
} }
} }
span.inline-errors {
margin-left: 10px;
padding: 2px 3px;
background: #FFE5E5;
color: #CE2525;
font-size: 13px;
}
span.actions { span.actions {
position: absolute; position: absolute;
top: 0px; top: 0px;
@ -149,9 +149,9 @@ form.formtastic {
&.drag { &.drag {
cursor: move; cursor: move;
background: transparent image-url("locomotive/list/icons/toggle_off.png") repeat 0 0; background: transparent image-url("locomotive/list/icons/move_off.png") repeat 0 0;
&:hover { &:hover {
background-image: image-url("locomotive/list/icons/toggle.png"); background-image: image-url("locomotive/list/icons/move.png");
} }
} }
} }
@ -592,23 +592,34 @@ form.formtastic {
li.custom-field { li.custom-field {
height: auto; height: auto;
clear: both;
& > .col {
float: left;
margin-right: 20px;
}
.editable { .editable {
display: inline-block; display: inline-block;
line-height: 16px; line-height: 16px;
width: 20px;
} }
span.handle { .handle {
position: relative; position: relative;
top: 3px; top: 4px;
margin-left: 5px; margin-left: 5px;
margin-right: 2px;
cursor: move; cursor: move;
} }
span.label-input { .label-input {
margin-right: 2px;
input[type=text] { input[type=text] {
float: none; float: none;
display: inline; display: inline-block;
@include default-input-style; @include default-input-style;
margin-left: 5px; margin-left: 5px;
@ -621,26 +632,31 @@ form.formtastic {
} }
} }
span.type-input { .type-input {
display: inline-block;
width: 150px; width: 150px;
.editable { .editable {
// font-style: italic;
color: #585A69; color: #585A69;
font-weight: normal; font-weight: normal;
width: 150px;
} }
} }
span.required-input { .required-input {
margin-left: 10px;
label { label {
float: none; float: none;
width: auto; width: auto;
font-weight: normal; font-weight: normal;
} }
.toggleSwitch {
display: inline-block;
position: relative;
top: 0px;
margin-left: 5px;
}
} }
} // li.custom-field } // li.custom-field
@ -661,6 +677,7 @@ form.formtastic {
} // > li } // > li
&.nested { &.nested {
clear: both;
width: 858px; width: 858px;
border: none; border: none;
@include border-radius(0); @include border-radius(0);

View File

@ -37,7 +37,7 @@ module Locomotive
## validations ## ## validations ##
validates_presence_of :site, :name, :slug validates_presence_of :site, :name, :slug
validates_uniqueness_of :slug, :scope => :site_id validates_uniqueness_of :slug, :scope => :site_id
validates_size_of :entries_custom_fields, :minimum => 1, :message => :array_too_short validates_size_of :entries_custom_fields, :minimum => 1, :message => :too_few_custom_fields
## behaviours ## ## behaviours ##
custom_fields_for :entries custom_fields_for :entries
@ -103,12 +103,15 @@ module Locomotive
def bubble_fields_errors_up def bubble_fields_errors_up
return if self.errors[:entries_custom_fields].empty? return if self.errors[:entries_custom_fields].empty?
self.errors.set(:entries_custom_fields, []) hash = { :base => self.errors[:entries_custom_fields] }
self.entries_custom_fields.each do |field| self.entries_custom_fields.each do |field|
next if field.valid? next if field.valid?
self.errors.add(:entries_custom_fields, field.errors.to_a) key = field.persisted? ? field._id.to_s : field.position.to_i
hash[key] = field.errors.to_a
end end
self.errors.set(:entries_custom_fields, hash)
end end
end end

View File

@ -20,19 +20,17 @@
= f.semantic_fields_for :contents_custom_field, CustomFields::Field.new do |g| = f.semantic_fields_for :contents_custom_field, CustomFields::Field.new do |g|
%span.handle .handle.col
= image_tag 'locomotive/form/icons/drag.png' = image_tag 'locomotive/form/icons/drag.png'
%span.label-input .label-input.col
= g.text_field :label, :class => 'label' = g.text_field :label, :class => 'label'
%span.type-input .type-input.col
= g.select :type, options_for_custom_field_type, {}, { :class => 'type' } = g.select :type, options_for_custom_field_type, {}, { :class => 'type' }
%span.required-input .required-input.col
= g.check_box :required, :class => 'required' = g.check_box :required, :class => 'required', :'data-on-label' => t('.required'), :'data-off-label' => t('.optional')
= g.label :required, t('.is_required')
%ol.nested{ :style => 'display: none' } %ol.nested{ :style => 'display: none' }
@ -50,6 +48,8 @@
= link_to 'toggle', '#', :class => 'toggle' = link_to 'toggle', '#', :class => 'toggle'
= link_to 'x', '#', :class => 'remove', :confirm => t('locomotive.messages.confirm') = link_to 'x', '#', :class => 'remove', :confirm => t('locomotive.messages.confirm')
.clear
%script{ :type => 'text/html', :id => 'select_options_list' } %script{ :type => 'text/html', :id => 'select_options_list' }

View File

@ -5,10 +5,3 @@
- if current_site.locales.size > 1 - if current_site.locales.size > 1
.action .action
= render 'locomotive/shared/locale_picker_link' = render 'locomotive/shared/locale_picker_link'
/ = link_to '#', :id => 'content-locale-picker-link', :class => 'button' do
/ %span.hand
/ &nbsp;
/
/ = image_tag "locomotive/icons/flags/#{current_content_locale}.png", :class => 'flag'
/
/ %span.text= current_content_locale

View File

@ -71,7 +71,8 @@ en:
has_many: has_many:
empty: Empty empty: Empty
form: form:
is_required: is required required: Required
optional: Optional
default_label: Field name default_label: Field name
select_options: select_options:
ask_name: "Type the label of the option" ask_name: "Type the label of the option"

View File

@ -16,6 +16,7 @@ en:
page: page:
liquid_syntax: "Liquid Syntax error ('%{error}' on '%{fullpath}')" liquid_syntax: "Liquid Syntax error ('%{error}' on '%{fullpath}')"
liquid_extend: "The page '%{fullpath}' extends a template which does not exist" liquid_extend: "The page '%{fullpath}' extends a template which does not exist"
too_few_custom_fields: "At least, one custom field is required"
attributes: attributes:
defaults: defaults:

View File

@ -63,9 +63,9 @@ x edit my site
x destroy x destroy
x public_form (previously api something) x public_form (previously api something)
x bug text formatting x bug text formatting
x custom_fields: use the appropriate icon to drag select options
- 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
- i18n - i18n
x add locales a site responds to x add locales a site responds to
x locale switcher x locale switcher
@ -84,10 +84,8 @@ x edit my site
- i18n - i18n
- insert image - insert image
- bugs: - bugs:
- unable to toggle the "required" check_boxes for content types x unable to toggle the "required" check_boxes for content types
- 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

@ -388,7 +388,7 @@ Backbone.ModelBinding = (function(Backbone, _, $){
array = _.without(array, value); array = _.without(array, value);
data[attr_name] = array; data[attr_name] = array;
} else } else
data[attr_name] = value; data[attr_name] = checked;
model.set(data); model.set(data);
}; };