make the edition of content types more robust (ex: better errors handler)
This commit is contained in:
parent
09d6060633
commit
b8b8cef089
BIN
app/assets/images/locomotive/list/icons/move.png
Normal file
BIN
app/assets/images/locomotive/list/icons/move.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 356 B |
BIN
app/assets/images/locomotive/list/icons/move_off.png
Normal file
BIN
app/assets/images/locomotive/list/icons/move_off.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 359 B |
@ -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
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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, @)
|
@ -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()
|
||||
|
||||
|
@ -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}")
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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' }
|
||||
|
||||
|
@ -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
|
||||
/
|
||||
/
|
||||
/ = image_tag "locomotive/icons/flags/#{current_content_locale}.png", :class => 'flag'
|
||||
/
|
||||
/ %span.text= current_content_locale
|
@ -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"
|
||||
|
@ -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:
|
||||
|
6
doc/TODO
6
doc/TODO
@ -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
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user