locomotive_cms 2.0.0.rc4 → 2.0.0.rc5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/app/assets/images/locomotive/list/icons/toggle.png +0 -0
  2. data/app/assets/images/locomotive/list/icons/toggle_off.png +0 -0
  3. data/app/assets/javascripts/locomotive/application.js.coffee +2 -2
  4. data/app/assets/javascripts/locomotive/models/page.js.coffee +1 -1
  5. data/app/assets/javascripts/locomotive/utils/core_ext.js +2 -2
  6. data/app/assets/javascripts/locomotive/views/content_types/custom_field_entry_view.js.coffee +2 -0
  7. data/app/assets/javascripts/locomotive/views/content_types/edit_view.coffee +0 -1
  8. data/app/assets/javascripts/locomotive/views/editable_elements/long_text_view.js.coffee +30 -2
  9. data/app/assets/javascripts/locomotive/views/editable_elements/short_text_view.js.coffee +7 -19
  10. data/app/assets/javascripts/locomotive/views/inline_editor/application_view.js.coffee +2 -6
  11. data/app/assets/javascripts/locomotive/views/inline_editor/toolbar_view.js.coffee +0 -6
  12. data/app/assets/javascripts/locomotive/views/pages/_form_view.js.coffee +1 -1
  13. data/app/assets/javascripts/locomotive/views/pages/edit_view.js.coffee +6 -3
  14. data/app/assets/javascripts/locomotive/views/shared/form_view.js.coffee +13 -1
  15. data/app/assets/javascripts/locomotive/views/theme_assets/index_view.js.coffee +12 -4
  16. data/app/assets/stylesheets/locomotive/backoffice/application.css.scss +23 -0
  17. data/app/assets/stylesheets/locomotive/backoffice/formtastic_changes.css.scss +15 -0
  18. data/app/assets/stylesheets/locomotive/backoffice/layout.css.scss +1 -1
  19. data/app/mailers/locomotive/notifications.rb +1 -1
  20. data/app/models/locomotive/content_entry.rb +1 -1
  21. data/app/models/locomotive/extensions/site/locales.rb +32 -1
  22. data/app/models/locomotive/extensions/site/subdomain_domains.rb +6 -2
  23. data/app/models/locomotive/page.rb +1 -1
  24. data/app/views/locomotive/notifications/new_content_entry.html.haml +12 -5
  25. data/app/views/locomotive/pages/_form.html.haml +1 -1
  26. data/app/views/locomotive/shared/_form_actions.html.haml +1 -1
  27. data/app/views/locomotive/shared/_head.html.haml +5 -2
  28. data/app/views/locomotive/theme_assets/index.html.haml +1 -1
  29. data/config/initializers/haml.rb +2 -1
  30. data/config/locales/admin_ui.de.yml +1 -0
  31. data/config/locales/admin_ui.en.yml +3 -0
  32. data/config/locales/admin_ui.es.yml +1 -0
  33. data/config/locales/admin_ui.fr.yml +2 -0
  34. data/config/locales/admin_ui.it.yml +1 -0
  35. data/config/locales/admin_ui.nl.yml +1 -0
  36. data/config/locales/admin_ui.no.yml +1 -0
  37. data/config/locales/admin_ui.pt-BR.yml +1 -0
  38. data/config/locales/admin_ui.ru.yml +1 -0
  39. data/config/locales/default.en.yml +2 -0
  40. data/config/locales/default.fr.yml +2 -0
  41. data/lib/generators/locomotive/install/templates/README +2 -2
  42. data/lib/locomotive.rb +1 -0
  43. data/lib/locomotive/action_controller/responder.rb +8 -0
  44. data/lib/locomotive/core_ext.rb +1 -1
  45. data/lib/locomotive/dependencies.rb +1 -0
  46. data/lib/locomotive/haml.rb +32 -0
  47. data/lib/locomotive/render.rb +2 -1
  48. data/lib/locomotive/version.rb +1 -1
  49. data/lib/locomotive_cms.rb +1 -0
  50. data/vendor/assets/javascripts/locomotive/form_submit_notification.js +39 -0
  51. metadata +97 -72
@@ -4,9 +4,9 @@
4
4
  #= require_tree ./views
5
5
 
6
6
  window.Locomotive =
7
- mounted_on: '/locomotive' # default path
7
+ mounted_on: window.Locomotive.mounted_on
8
8
  Models: {}
9
9
  Collections: {}
10
10
  Views: {}
11
11
 
12
- window.Locomotive.Views.Memberships = {}
12
+ window.Locomotive.Views.Memberships = {}
@@ -16,7 +16,7 @@ class Locomotive.Models.Page extends Backbone.Model
16
16
 
17
17
  toJSON: ->
18
18
  _.tap super, (hash) =>
19
- _.each ['content_type_id_text', 'edit_url', 'parent_id_text', 'response_type_text'], (key) => delete hash[key]
19
+ _.each ['fullpath', 'localized_fullpaths', 'templatized_from_parent', 'target_klass_name_text', 'content_type_id_text', 'edit_url', 'parent_id_text', 'response_type_text'], (key) => delete hash[key]
20
20
 
21
21
  delete hash['editable_elements']
22
22
  hash.editable_elements = @get('editable_elements').toJSONForSave() if @get('editable_elements')? && @get('editable_elements').length > 0
@@ -18,9 +18,9 @@
18
18
 
19
19
  String.prototype.slugify = function(sep) {
20
20
  if (typeof sep == 'undefined') sep = '_';
21
- var alphaNumRegexp = new RegExp('[^a-zA-Z0-9\\' + sep + ']', 'g');
21
+ var alphaNumRegexp = new RegExp('[^\\w\\' + sep + ']', 'g');
22
22
  var avoidDuplicateRegexp = new RegExp('[\\' + sep + ']{2,}', 'g');
23
- return this.replace(/\s/g, sep).replace(alphaNumRegexp, '').replace(avoidDuplicateRegexp, sep).toLowerCase()
23
+ return this.replace(/\s/g, sep).replace(alphaNumRegexp, '').replace(avoidDuplicateRegexp, sep).toLowerCase();
24
24
  }
25
25
 
26
26
  window.addParameterToURL = function(key, value, context) { // code from http://stackoverflow.com/questions/486896/adding-a-parameter-to-the-url-with-javascript
@@ -78,8 +78,10 @@ class Locomotive.Views.ContentTypes.CustomFieldEntryView extends Backbone.View
78
78
  form = @$('ol')
79
79
 
80
80
  if form.is(':hidden')
81
+ @$('a.toggle').addClass('open')
81
82
  form.slideDown()
82
83
  else
84
+ @$('a.toggle').removeClass('open')
83
85
  form.slideUp()
84
86
 
85
87
  show_error: (message) ->
@@ -11,5 +11,4 @@ class Locomotive.Views.ContentTypes.EditView extends Locomotive.Views.ContentTyp
11
11
 
12
12
  if custom_field.isNew() # assign an id for each new custom field
13
13
  custom_field.set id: data._id, _id: data._id
14
- console.log(custom_field)
15
14
 
@@ -2,7 +2,35 @@
2
2
 
3
3
  Locomotive.Views.EditableElements ||= {}
4
4
 
5
- class Locomotive.Views.EditableElements.LongTextView extends Locomotive.Views.EditableElements.ShortTextView
5
+ class Locomotive.Views.EditableElements.LongTextView extends Backbone.View
6
+
7
+ tagName: 'li'
8
+
9
+ className: 'text input html'
10
+
11
+ render: ->
12
+ $(@el).html(ich.editable_text_input(@model.toJSON()))
13
+
14
+ return @
15
+
16
+ after_render: ->
17
+ settings = _.extend {}, @tinymce_settings(),
18
+ oninit: ((editor) =>
19
+ $.cmd 'S', (() =>
20
+ @model.set(content: editor.getBody().innerHTML)
21
+ $(@el).parents('form').trigger('submit')
22
+ ), [], ignoreCase: true, document: editor.dom.doc),
23
+ onchange_callback: (editor) =>
24
+ @model.set(content: editor.getBody().innerHTML)
25
+
26
+ @$('textarea').tinymce(settings)
6
27
 
7
28
  tinymce_settings: ->
8
- window.Locomotive.tinyMCE.defaultSettings
29
+ window.Locomotive.tinyMCE.defaultSettings
30
+
31
+ refresh: ->
32
+ # do nothing
33
+
34
+ remove: ->
35
+ @$('textarea').tinymce().destroy()
36
+ super
@@ -4,31 +4,19 @@ class Locomotive.Views.EditableElements.ShortTextView extends Backbone.View
4
4
 
5
5
  tagName: 'li'
6
6
 
7
- className: 'text input html'
7
+ className: 'text input short'
8
8
 
9
9
  render: ->
10
10
  $(@el).html(ich.editable_text_input(@model.toJSON()))
11
11
 
12
+ @$('textarea').bind 'keyup', (event) =>
13
+ input = $(event.target)
14
+ @model.set(content: input.val())
15
+
12
16
  return @
13
17
 
14
18
  after_render: ->
15
- settings = _.extend {}, @tinymce_settings(),
16
- oninit: ((editor) =>
17
- $.cmd 'S', (() =>
18
- @model.set(content: editor.getBody().innerHTML)
19
- $(@el).parents('form').trigger('submit')
20
- ), [], ignoreCase: true, document: editor.dom.doc),
21
- onchange_callback: (editor) =>
22
- @model.set(content: editor.getBody().innerHTML)
23
-
24
- @$('textarea').tinymce(settings)
25
-
26
- tinymce_settings: ->
27
- window.Locomotive.tinyMCE.minimalSettings
28
-
29
- refresh: ->
30
19
  # do nothing
31
20
 
32
- remove: ->
33
- @$('textarea').tinymce().destroy()
34
- super
21
+ refresh: ->
22
+ # do nothing
@@ -26,15 +26,13 @@ class Locomotive.Views.InlinEditor.ApplicationView extends Backbone.View
26
26
  iframe = @iframe
27
27
 
28
28
  iframe.load =>
29
- console.log('iframe loading')
30
-
31
29
  if @_$('meta[name=inline-editor]').size() > 0
32
30
  # bind the resize event. When the iFrame's size changes, update its height
33
- iframe_content = iframe.contents().find('body')
31
+ iframe_content = iframe.contents()
34
32
  iframe_content.resize ->
35
33
  elem = $(this)
36
34
 
37
- if elem.outerHeight(true) > $('body').outerHeight(true) # Resize the iFrame.
35
+ if elem.outerHeight(true) > iframe.outerHeight(true) # Resize the iFrame.
38
36
  iframe.css height: elem.outerHeight(true)
39
37
 
40
38
  # Resize the iFrame immediately.
@@ -46,8 +44,6 @@ class Locomotive.Views.InlinEditor.ApplicationView extends Backbone.View
46
44
  @enhance_iframe_links()
47
45
 
48
46
  set_page: (attributes) ->
49
- console.log('set_page')
50
-
51
47
  @page = new Locomotive.Models.Page(attributes)
52
48
 
53
49
  @toolbar_view.model = @page
@@ -13,8 +13,6 @@ class Locomotive.Views.InlinEditor.ToolbarView extends Backbone.View
13
13
  render: ->
14
14
  super
15
15
 
16
- console.log('render toolbar')
17
-
18
16
  @enable_editing_mode_checkbox()
19
17
 
20
18
  @enable_content_locale_picker()
@@ -22,8 +20,6 @@ class Locomotive.Views.InlinEditor.ToolbarView extends Backbone.View
22
20
  @
23
21
 
24
22
  notify: (aloha_editable) ->
25
- console.log('editable_element has been modified...')
26
-
27
23
  window.bar = aloha_editable
28
24
 
29
25
  element_id = aloha_editable.obj.attr('data-element-id')
@@ -125,8 +121,6 @@ class Locomotive.Views.InlinEditor.ToolbarView extends Backbone.View
125
121
  context.find('span.text').html(values[1])
126
122
 
127
123
  refresh: ->
128
- console.log('refreshing toolbar...')
129
-
130
124
  @$('h1').html(@model.get('title')).removeClass()
131
125
 
132
126
  if @$('.editing-mode input[type=checkbox]').is(':checked')
@@ -116,7 +116,7 @@ class Locomotive.Views.Pages.FormView extends Locomotive.Views.Shared.FormView
116
116
  @$('li#page_slug_input').show()
117
117
  @$('li#page_templatized_input, li#page_target_klass_name_input').hide()
118
118
  else
119
- @$('li#page_templatized_input, li#page_target_klass_name_input').show()
119
+ @$('li#page_templatized_input').show() unless @model.get('redirect')
120
120
 
121
121
  enable_response_type_select: ->
122
122
  @$('li#page_response_type_input').change (event) =>
@@ -5,10 +5,14 @@ class Locomotive.Views.Pages.EditView extends Locomotive.Views.Pages.FormView
5
5
  save: (event) ->
6
6
  event.stopPropagation() & event.preventDefault()
7
7
 
8
+ form = $(event.target).trigger('ajax:beforeSend')
9
+
8
10
  @clear_errors()
9
11
 
10
12
  @model.save {},
11
13
  success: (model, response, xhr) =>
14
+ form.trigger('ajax:complete')
15
+
12
16
  model._normalize()
13
17
 
14
18
  if model.get('template_changed') == true
@@ -17,9 +21,8 @@ class Locomotive.Views.Pages.EditView extends Locomotive.Views.Pages.FormView
17
21
  @refresh_editable_elements()
18
22
 
19
23
  error: (model, xhr) =>
24
+ form.trigger('ajax:complete')
25
+
20
26
  errors = JSON.parse(xhr.responseText)
21
27
 
22
28
  @show_errors errors
23
-
24
-
25
-
@@ -16,6 +16,9 @@ class Locomotive.Views.Shared.FormView extends Backbone.View
16
16
  # allow users to save with CTRL+S or CMD+s
17
17
  @enable_save_with_keys_combination()
18
18
 
19
+ # enable form notifications
20
+ @enable_form_notifications()
21
+
19
22
  return @
20
23
 
21
24
  save: (event) ->
@@ -24,6 +27,8 @@ class Locomotive.Views.Shared.FormView extends Backbone.View
24
27
  save_in_ajax: (event, options) ->
25
28
  event.stopPropagation() & event.preventDefault()
26
29
 
30
+ form = $(event.target).trigger('ajax:beforeSend')
31
+
27
32
  @clear_errors()
28
33
 
29
34
  options ||= { headers: {}, on_success: null, on_error: null }
@@ -33,11 +38,15 @@ class Locomotive.Views.Shared.FormView extends Backbone.View
33
38
  @model.save {},
34
39
  headers: options.headers
35
40
  success: (model, response, xhr) =>
41
+ form.trigger('ajax:complete')
42
+
36
43
  model.attributes = previous_attributes
37
44
 
38
45
  options.on_success(response, xhr) if options.on_success
39
46
 
40
47
  error: (model, xhr) =>
48
+ form.trigger('ajax:complete')
49
+
41
50
  errors = JSON.parse(xhr.responseText)
42
51
 
43
52
  @show_errors errors
@@ -72,7 +81,10 @@ class Locomotive.Views.Shared.FormView extends Backbone.View
72
81
  content.slideUp 100, -> parent.addClass('folded')
73
82
 
74
83
  enable_save_with_keys_combination: ->
75
- $.cmd 'S', (() => @$('form').trigger('submit')), [], ignoreCase: true
84
+ $.cmd 'S', (() => @$('form input[type=submit]').trigger('click')), [], ignoreCase: true
85
+
86
+ enable_form_notifications: ->
87
+ @$('form').formSubmitNotification()
76
88
 
77
89
  after_inputs_fold: ->
78
90
  # overide this method if necessary
@@ -7,7 +7,7 @@ class Locomotive.Views.ThemeAssets.IndexView extends Backbone.View
7
7
  _lists_views: []
8
8
 
9
9
  initialize: ->
10
- _.bindAll(@, 'add_asset')
10
+ _.bindAll(@, 'insert_asset')
11
11
 
12
12
  render: ->
13
13
  @build_uploader()
@@ -29,16 +29,24 @@ class Locomotive.Views.ThemeAssets.IndexView extends Backbone.View
29
29
  input = form.find('input[type=file]')
30
30
  link = form.find('a.new')
31
31
 
32
+ form.formSubmitNotification()
33
+
32
34
  link.bind 'click', (event) ->
33
35
  event.stopPropagation() & event.preventDefault()
34
36
  input.click()
35
37
 
36
38
  input.bind 'change', (event) =>
39
+ form.trigger('ajax:beforeSend')
37
40
  _.each event.target.files, (file) =>
38
41
  asset = new Locomotive.Models.ThemeAsset(source: file)
39
- asset.save {}, success: @add_asset, headers: { 'X-Flash': true }
40
-
41
- add_asset: (model) ->
42
+ asset.save {},
43
+ success: (model, response, xhr) =>
44
+ form.trigger('ajax:complete')
45
+ @insert_asset(model)
46
+ error: (() => form.trigger('ajax:complete'))
47
+ headers: { 'X-Flash': true }
48
+
49
+ insert_asset: (model) ->
42
50
  list_view = @pick_list_view(model.get('content_type'))
43
51
  list_view.collection.add(model)
44
52
 
@@ -314,6 +314,29 @@ ul.list {
314
314
  }
315
315
  }
316
316
 
317
+ /* ___ form notification ___ */
318
+
319
+ #form-submit-notification {
320
+ position: fixed;
321
+ top: 0px;
322
+ right: 0px;
323
+ z-index: 9999;
324
+
325
+ > div {
326
+ padding: 5px 10px;
327
+
328
+ background-color: #fffbe5;
329
+ border-left: 4px solid #efe4a5;
330
+ border-bottom: 4px solid #efe4a5;
331
+
332
+ text-align: center;
333
+ @include single-text-shadow(rgba(255, 255, 255, 1), 0px, 1px, 0px);
334
+ font-weight: bold;
335
+ font-size: 12px;
336
+ color: #aa9a79;
337
+ }
338
+ }
339
+
317
340
  /* ___ paragraph (for help for example) ___ */
318
341
 
319
342
  p span.code {
@@ -157,6 +157,10 @@ form.formtastic {
157
157
  &:hover {
158
158
  background-image: image-url("locomotive/list/icons/toggle.png");
159
159
  }
160
+ &.open {
161
+ @include rotate(180deg);
162
+ }
163
+ @include single-transition(transform, 0.5s);
160
164
  }
161
165
 
162
166
  &.drag {
@@ -291,6 +295,17 @@ form.formtastic {
291
295
  }
292
296
  } // li.string, li.password
293
297
 
298
+ &.text {
299
+
300
+ &.short textarea {
301
+ padding: 5px;
302
+ height: 28px;
303
+ width: 696px;
304
+ overflow-y: hidden;
305
+ }
306
+
307
+ } // li.text
308
+
294
309
  &.locale, &.locales {
295
310
  .list {
296
311
  margin-left: 150px;
@@ -176,7 +176,7 @@ body {
176
176
  }
177
177
  }
178
178
 
179
- input[type=submit] {
179
+ input[type=submit], button[type=submit] {
180
180
  @include light-button;
181
181
  }
182
182
 
@@ -4,7 +4,7 @@ module Locomotive
4
4
  default :from => Locomotive.config.mailer_sender
5
5
 
6
6
  def new_content_entry(account, entry)
7
- @account, @entry, @type = account, entry.to_presenter, entry.content_type
7
+ @account, @entry, @type = account, entry, entry.content_type
8
8
 
9
9
  subject = t('locomotive.notifications.new_content_entry.subject', :type => @type.name, :locale => account.locale)
10
10
 
@@ -146,7 +146,7 @@ module Locomotive
146
146
  return if !self.content_type.public_submission_enabled? || self.content_type.public_submission_accounts.blank?
147
147
 
148
148
  self.site.accounts.each do |account|
149
- next unless self.content_type.public_submission_accounts.include?(account._id)
149
+ next unless self.content_type.public_submission_accounts.map(&:to_s).include?(account._id.to_s)
150
150
 
151
151
  Locomotive::Notifications.new_content_entry(account, self).deliver
152
152
  end
@@ -10,8 +10,12 @@ module Locomotive
10
10
  ## fields ##
11
11
  field :locales, :type => 'RawArray', :default => []
12
12
 
13
+ ## validations ##
14
+ validate :can_not_remove_default_locale
15
+
13
16
  ## callbacks ##
14
- after_validation :add_default_locale
17
+ after_validation :add_default_locale
18
+ before_update :verify_localized_default_pages_integrity
15
19
 
16
20
  end
17
21
 
@@ -48,6 +52,10 @@ module Locomotive
48
52
  self.locales.first || Locomotive.config.site_locales.first
49
53
  end
50
54
 
55
+ def default_locale_was
56
+ self.locales_was.first || Locomotive.config.site_locales.first
57
+ end
58
+
51
59
  def locale_fallbacks(locale)
52
60
  [locale.to_s] + (locales - [locale.to_s])
53
61
  end
@@ -58,6 +66,29 @@ module Locomotive
58
66
  self.locales = [Locomotive.config.site_locales.first] if self.locales.blank?
59
67
  end
60
68
 
69
+ def can_not_remove_default_locale
70
+ if self.persisted? && !self.locales.include?(self.default_locale_was)
71
+ self.errors.add :locales, I18n.t(:default_locale_removed, :scope => [:errors, :messages, :site])
72
+ end
73
+ end
74
+
75
+ def verify_localized_default_pages_integrity
76
+ if self.persisted? && self.locales_changed?
77
+ self.pages.where(:"slug.#{self.default_locale_was}".in => %w(index 404), :depth => 0).each do |page|
78
+ modifications = { 'title' => {}, 'slug' => {} }
79
+
80
+ self.locales.each do |locale|
81
+ slug = page.attributes['slug'][self.default_locale_was]
82
+
83
+ modifications['slug'][locale] = slug
84
+ modifications['title'][locale] = page.attributes['title'][locale] || ::I18n.t("attributes.defaults.pages.#{slug}.title", :locale => locale)
85
+ end
86
+
87
+ page.collection.update({ :_id => page._id }, { '$set' => modifications })
88
+ end
89
+ end
90
+ end
91
+
61
92
  end
62
93
 
63
94
  end