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: ->
_.tap super, (hash) =>
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

View File

@ -12,8 +12,6 @@ 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: ->
@ -64,12 +62,20 @@ class Locomotive.Views.ContentTypes.FormView extends Locomotive.Views.Shared.For
target.show()
show_error: (attribute, message, html) ->
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
if attribute != 'entries_custom_fields'
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: ->
@custom_fields_view.remove()

View File

@ -28,6 +28,8 @@ class Locomotive.Views.ContentTypes.CustomFieldEntryView extends Backbone.View
return @
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()
@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)
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) ->
event.stopPropagation() & event.preventDefault()
@ -60,13 +62,13 @@ class Locomotive.Views.ContentTypes.CustomFieldEntryView extends Backbone.View
form.slideUp()
show_error: (message) ->
html = $("<span class=\"inline-errors\">#{message}</div>")
@$('span.required-input').after(html)
html = $("<span class=\"inline-errors\">#{message}</span>")
@$('.required-input').after(html)
remove: (event) ->
event.stopPropagation() & event.preventDefault()
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()
@options.parent_view.remove_entry(@model, @)

View File

@ -26,7 +26,7 @@ class Locomotive.Views.ContentTypes.CustomFieldsView extends Backbone.View
make_list_sortable: ->
@sortable_list = @$('> ul').sortable
handle: 'span.handle'
handle: '.handle'
items: 'li.custom-field'
axis: 'y'
update: @refresh_position_entries
@ -35,6 +35,13 @@ class Locomotive.Views.ContentTypes.CustomFieldsView extends Backbone.View
_.each @_entry_views, (view) ->
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) ->
event.stopPropagation() & event.preventDefault()

View File

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

View File

@ -12,6 +12,16 @@ form.formtastic {
padding-bottom: 1px;
span.inline-errors {
margin-left: 10px;
padding: 2px 3px;
background: #FFE5E5;
color: #CE2525;
font-size: 13px;
}
legend {
display: block;
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 {
position: absolute;
top: 0px;
@ -149,9 +149,9 @@ form.formtastic {
&.drag {
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 {
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 {
height: auto;
clear: both;
& > .col {
float: left;
margin-right: 20px;
}
.editable {
display: inline-block;
line-height: 16px;
width: 20px;
}
span.handle {
.handle {
position: relative;
top: 3px;
top: 4px;
margin-left: 5px;
margin-right: 2px;
cursor: move;
}
span.label-input {
.label-input {
margin-right: 2px;
input[type=text] {
float: none;
display: inline;
display: inline-block;
@include default-input-style;
margin-left: 5px;
@ -621,26 +632,31 @@ form.formtastic {
}
}
span.type-input {
display: inline-block;
.type-input {
width: 150px;
.editable {
// font-style: italic;
color: #585A69;
font-weight: normal;
width: 150px;
}
}
span.required-input {
margin-left: 10px;
.required-input {
label {
float: none;
width: auto;
font-weight: normal;
}
.toggleSwitch {
display: inline-block;
position: relative;
top: 0px;
margin-left: 5px;
}
}
} // li.custom-field
@ -661,6 +677,7 @@ form.formtastic {
} // > li
&.nested {
clear: both;
width: 858px;
border: none;
@include border-radius(0);

View File

@ -37,7 +37,7 @@ module Locomotive
## validations ##
validates_presence_of :site, :name, :slug
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 ##
custom_fields_for :entries
@ -103,12 +103,15 @@ module Locomotive
def bubble_fields_errors_up
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|
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
self.errors.set(:entries_custom_fields, hash)
end
end

View File

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

View File

@ -5,10 +5,3 @@
- if current_site.locales.size > 1
.action
= 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:
empty: Empty
form:
is_required: is required
required: Required
optional: Optional
default_label: Field name
select_options:
ask_name: "Type the label of the option"

View File

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

View File

@ -63,9 +63,9 @@ x edit my site
x destroy
x public_form (previously api something)
x bug text formatting
x custom_fields: use the appropriate icon to drag select options
- use list_or_group_entries instead of ordered_entries
- bug ui with contents popup
- custom_fields: use the appropriate icon to drag select options
- i18n
x add locales a site responds to
x locale switcher
@ -84,10 +84,8 @@ x edit my site
- i18n
- insert image
- 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 ?)
- message to notify people if their browser is too old

View File

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