ab_admin 0.3.5 → 0.3.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. data/Gemfile +3 -3
  2. data/TODO +2 -1
  3. data/ab_admin.gemspec +2 -2
  4. data/app/assets/javascripts/ab_admin/components/admin_assets.js.coffee +2 -22
  5. data/app/assets/javascripts/ab_admin/components/croppable_image.js.coffee +3 -3
  6. data/app/assets/javascripts/ab_admin/components/gmaps.js.coffee +0 -38
  7. data/app/assets/javascripts/ab_admin/components/in_place_edit.js.coffee +2 -1
  8. data/app/assets/javascripts/ab_admin/components/init_nested_filelds.js.coffee +1 -0
  9. data/app/assets/javascripts/ab_admin/core/init.js.coffee +2 -0
  10. data/app/assets/javascripts/ab_admin/core/pjax.js.coffee +6 -6
  11. data/app/assets/javascripts/ab_admin/core/ui_utils.js.coffee +7 -7
  12. data/app/assets/javascripts/ab_admin/core/utils.js.coffee +19 -1
  13. data/app/assets/javascripts/ab_admin/core/view_layout.js.coffee +44 -0
  14. data/app/assets/stylesheets/ab_admin/bootstrap_and_overrides.css.scss +22 -0
  15. data/app/assets/stylesheets/ab_admin/components/_base.css.scss +3 -3
  16. data/app/assets/stylesheets/ab_admin/components/_form.css.scss +1 -1
  17. data/app/assets/stylesheets/ab_admin/components/_navigation.css.scss +7 -1
  18. data/app/assets/stylesheets/ab_admin/components/_table_view.css.scss +4 -0
  19. data/app/assets/stylesheets/ab_admin/components/_view_layout.css.scss +65 -0
  20. data/app/assets/stylesheets/ab_admin/fileupload.css.scss +1 -0
  21. data/app/controllers/admin/base_controller.rb +30 -14
  22. data/app/controllers/admin/static_pages_controller.rb +3 -1
  23. data/app/views/admin/base/_search_layout.html.slim +2 -0
  24. data/app/views/admin/base/create.js.erb +2 -2
  25. data/app/views/admin/base/edit.js.erb +3 -1
  26. data/app/views/admin/base/index.html.slim +5 -0
  27. data/app/views/admin/base/new.js.erb +3 -1
  28. data/app/views/admin/base/update.js.erb +1 -1
  29. data/app/views/admin/fileupload/_file.html.slim +1 -1
  30. data/app/views/admin/fileupload/_video.html.slim +9 -0
  31. data/app/views/admin/fileupload/_vtmpl.html.slim +10 -0
  32. data/app/views/admin/shared/_batch_actions.html.slim +9 -3
  33. data/app/views/admin/shared/_breadcrumbs.html.slim +5 -6
  34. data/app/views/admin/shared/_flash.js.erb +3 -0
  35. data/app/views/admin/shared/inputs/_checkbox_tree.html.slim +14 -0
  36. data/app/views/admin/structures/_form.html.slim +5 -2
  37. data/app/views/layouts/admin/_footer.html.slim +1 -0
  38. data/app/views/layouts/admin/_navigation.html.slim +5 -7
  39. data/app/views/layouts/admin/application.html.slim +1 -1
  40. data/config/locales/en.yml +4 -10
  41. data/config/locales/it.yml +1 -8
  42. data/config/locales/ru.yml +4 -10
  43. data/features/dsl/export.feature +6 -6
  44. data/lib/ab_admin/concerns/utilities.rb +3 -3
  45. data/lib/ab_admin/controllers/head_options.rb +1 -0
  46. data/lib/ab_admin/core_ext/string.rb +3 -2
  47. data/lib/ab_admin/hooks/paginate_hooks.rb +1 -0
  48. data/lib/ab_admin/models/asset.rb +4 -0
  49. data/lib/ab_admin/models/attachment_file.rb +0 -4
  50. data/lib/ab_admin/models/type_model.rb +10 -0
  51. data/lib/ab_admin/models/user.rb +1 -1
  52. data/lib/ab_admin/utils.rb +2 -0
  53. data/lib/ab_admin/version.rb +1 -1
  54. data/lib/ab_admin/views/admin_helpers.rb +14 -6
  55. data/lib/ab_admin/views/admin_navigation_helpers.rb +4 -2
  56. data/lib/ab_admin/views/form_builder.rb +5 -2
  57. data/lib/ab_admin/views/helpers.rb +4 -0
  58. data/lib/ab_admin/views/inputs/ckeditor_input.rb +0 -1
  59. data/lib/generators/ab_admin/install/templates/config/nginx.conf +12 -7
  60. data/lib/generators/ab_admin/install/templates/models/structure.rb +2 -1
  61. data/lib/generators/ab_admin/resource/templates/_form.haml.erb +1 -1
  62. data/lib/generators/ab_admin/resource/templates/_form.slim.erb +1 -1
  63. metadata +12 -22
@@ -59,6 +59,7 @@
59
59
  padding-top: 10px;
60
60
  padding-left: 5px;
61
61
  z-index: 2;
62
+ position: relative;
62
63
  }
63
64
  .fileupload-button {
64
65
  z-index: 3;
@@ -93,6 +93,10 @@ class Admin::BaseController < ::InheritedResources::Base
93
93
 
94
94
  protected
95
95
 
96
+ def default_url_options
97
+ {format: nil}
98
+ end
99
+
96
100
  def batch_action_list
97
101
  self.class.batch_action_list ||= begin
98
102
  resource_class.batch_actions.map do |a|
@@ -106,6 +110,7 @@ class Admin::BaseController < ::InheritedResources::Base
106
110
  super
107
111
  base.class_eval do
108
112
  before_create :bind_current_user
113
+ before_save :bind_current_updater
109
114
  end
110
115
  end
111
116
 
@@ -126,16 +131,6 @@ class Admin::BaseController < ::InheritedResources::Base
126
131
  export_builder.render_options
127
132
  end
128
133
 
129
- def set_title
130
- name_for_lookup = params[:custom_action] || action_name
131
- lookups = [:"admin.#{controller_name}.actions.#{name_for_lookup}.title",
132
- :"admin.#{controller_name}.actions.#{name_for_lookup}",
133
- :"admin.actions.#{name_for_lookup}.title",
134
- :"admin.actions.#{name_for_lookup}",
135
- name_for_lookup]
136
- @page_title ||= [resource_class.model_name.human(count: 1), t(lookups.shift, default: lookups)].join(' - ')
137
- end
138
-
139
134
  def preview_resource_path(item)
140
135
  nil
141
136
  end
@@ -186,6 +181,16 @@ class Admin::BaseController < ::InheritedResources::Base
186
181
  end
187
182
  end
188
183
 
184
+ def set_title
185
+ name_for_lookup = params[:custom_action] || action_name
186
+ lookups = [:"admin.#{controller_name}.actions.#{name_for_lookup}.title",
187
+ :"admin.#{controller_name}.actions.#{name_for_lookup}",
188
+ :"admin.actions.#{name_for_lookup}.title",
189
+ :"admin.actions.#{name_for_lookup}",
190
+ name_for_lookup]
191
+ @page_title ||= t(lookups.shift, default: lookups)
192
+ end
193
+
189
194
  def parent_collection_path
190
195
  {action: :index, controller: "admin/#{parent_class.model_name.plural}"}
191
196
  end
@@ -215,7 +220,11 @@ class Admin::BaseController < ::InheritedResources::Base
215
220
  end
216
221
 
217
222
  def set_layout
218
- request.headers['X-PJAX'] ? false : 'admin/application'
223
+ pjax? ? false : 'admin/application'
224
+ end
225
+
226
+ def pjax?
227
+ request.headers['X-PJAX']
219
228
  end
220
229
 
221
230
  def back_or_collection
@@ -272,6 +281,10 @@ class Admin::BaseController < ::InheritedResources::Base
272
281
  resource.user_id = current_user.id if resource.respond_to?(:user_id)
273
282
  end
274
283
 
284
+ def bind_current_updater(*args)
285
+ resource.updater_id = current_user.id if resource.respond_to?(:updater_id)
286
+ end
287
+
275
288
  def xhr?
276
289
  request.xhr?
277
290
  end
@@ -303,9 +316,12 @@ class Admin::BaseController < ::InheritedResources::Base
303
316
  def render_unauthorized(exception)
304
317
  Rails.logger.debug "Access denied on #{exception.action} #{exception.subject.inspect}, user: #{current_user.try(:id)}"
305
318
 
306
- respond_to do |format|
307
- format.html { redirect_to (moderator? ? admin_root_path : root_path), alert: exception.message }
308
- format.any { head :unauthorized }
319
+ if pjax?
320
+ render partial: 'admin/shared/flash', locals: {flash: {alert: exception.message}}
321
+ elsif request.format.try(:html?)
322
+ redirect_to (moderator? ? admin_root_path : root_path), alert: exception.message
323
+ else
324
+ head :unauthorized
309
325
  end
310
326
  end
311
327
 
@@ -1,7 +1,9 @@
1
1
  class Admin::StaticPagesController < Admin::BaseController
2
2
  load_and_authorize_resource
3
3
 
4
- belongs_to :structure, singleton: true
4
+ defaults singleton: true
5
+
6
+ belongs_to :structure
5
7
 
6
8
  def settings
7
9
  {}
@@ -1,3 +1,5 @@
1
+ #toggle_sidebar_off.btn.btn-large = icon('chevron-left')
2
+ #toggle_sidebar_on.btn.btn-large = icon('chevron-right')
1
3
  h3= t('admin.search.title')
2
4
  = search_admin_form_for @search, url: collection_path do |f|
3
5
  - cache [I18n.locale, 'search_form_inside', resource_class.name, params[:q].hash] do
@@ -1,8 +1,8 @@
1
1
  <%
2
2
  form_wrap_id = dom_id(resource_class.new, 'list_edit')
3
- html = render('table', collection: [resource])[/<tr id[^>]+>.*<\/tr>/m].html_safe
3
+ html = render('table', collection: [resource]).match(/<tbody>(.*)<\/tbody>/m)[1].html_safe
4
4
  %>
5
5
  $('#<%= form_wrap_id %>').remove();
6
6
  $('#list tbody').prepend('<%= j html %>');
7
7
  $('#<%= dom_id(resource, 'list') %>').addClass('success').scrollToEl();
8
- $(document).trigger('admin:list_init');
8
+ $(document).trigger('admin:list_init');
@@ -5,6 +5,8 @@
5
5
  %>
6
6
  $('#<%= form_wrap_id %>').remove();
7
7
  $('#<%= el_id %>').after('<%= j html %>');
8
- $('#<%= form_wrap_id %> td').attr('colspan', $('#list tr:first th').length);
8
+ $('#<%= form_wrap_id %> td:first').attr('colspan', $('#list tr:first th').length);
9
9
  $('#<%= el_id %>').scrollToEl();
10
10
  $('#<%= form_wrap_id %> form').trigger('admin:form_init');
11
+
12
+ <%= render 'admin/shared/flash', flash: flash %>
@@ -11,3 +11,8 @@
11
11
  .btn-group
12
12
  - [50, 100, 500, 1000].each do |c|
13
13
  a.btn.per_page data-val=c href=url_for(params.merge(per_page: c)) class=('active' if c == collection.per_page) = c
14
+
15
+ - if pjax? && flash.present?
16
+ - flash.each do |k, v|
17
+ = javascript_tag %[flash("#{j v}", "#{k}")]
18
+
@@ -4,5 +4,7 @@
4
4
  %>
5
5
  $('#<%= form_wrap_id %>').remove();
6
6
  $('#list tbody').prepend('<%= j html %>');
7
- $('#<%= form_wrap_id %> td').attr('colspan', $('#list tr:first th').length);
7
+ $('#<%= form_wrap_id %> td:first').attr('colspan', $('#list tr:first th').length);
8
8
  $('#<%= form_wrap_id %> form').trigger('admin:form_init');
9
+
10
+ <%= render 'admin/shared/flash', flash: flash %>
@@ -1,6 +1,6 @@
1
1
  <%
2
2
  form_wrap_id = dom_id(resource, 'list_edit')
3
- html = render('table', collection: [resource])[/<tr id[^>]+>.*<\/tr>/m].html_safe
3
+ html = render('table', collection: [resource]).match(/<tbody>(.*)<\/tbody>/m)[1].html_safe
4
4
  %>
5
5
  $('#<%= form_wrap_id %>').remove();
6
6
  $('#<%= dom_id(resource, 'list') %>').replaceWith('<%= j html %>');
@@ -1,5 +1,5 @@
1
1
  .asset id="asset_#{file.id}" data-id=file.id
2
- a href=file.url target='_blank' = file.original_name
2
+ a href=file.url target='_blank' = file.human_name
3
3
  span== " (#{file.human_filesize}) - #{l(file.created_at, format: :long)}"
4
4
  = link_to icon('remove', true), admin_asset_path(file), remote: true, method: :delete, \
5
5
  class: 'del_asset btn btn-danger btn-mini', data: {confirm: t('admin.delete_confirmation')}
@@ -0,0 +1,9 @@
1
+ .asset id="asset_#{video.id}" data-id=video.id
2
+ = link_to icon('remove', true), admin_asset_path(video), remote: true, method: :delete, title: t('admin.delete'), class: 'del_asset', \
3
+ data: {confirm: t('admin.delete_confirmation')}
4
+ video controls='true'
5
+ source src=video.url
6
+ | Your browser does not support mp4 videos
7
+ .video-filename
8
+ a href=video.url target='_blank' = video.human_name
9
+ span== " (#{video.human_filesize}) - #{l(video.created_at, format: :long)}"
@@ -0,0 +1,10 @@
1
+ script#fileupload_vtmpl type="text/x-jquery-tmpl"
2
+ .asset id="asset_${id}" data-id='${id}'
3
+ = link_to icon('remove', true), '/admin/assets/${id}', remote: true, method: :delete, title: t('admin.delete'), \
4
+ class: 'del_asset btn btn-danger btn-mini', data: {confirm: t('admin.delete_confirmation')}
5
+ video controls='true'
6
+ source src='${url}'
7
+ | Your browser does not support mp4 videos
8
+ .video-filename
9
+ a href='${url}' target='_blank' ${original_name}
10
+ span &nbsp;(${human_filesize})
@@ -12,10 +12,16 @@
12
12
  - button_scopes.each do |name, opts|
13
13
  - active = params[opts[:as]]
14
14
  a.btn[href=(url_for(opts[:as] => (active ? nil : 1))) class=('active' if active)]= t "admin.scopes.#{name}"
15
+
16
+ a.btn.pull-left#columns_hider_show[href="#columns_hider" data-toggle='modal']= t 'admin.columns_hider.button'
17
+
18
+ .btn-group#view_layout
19
+ .btn data-css='main_wide' = icon('align-left')
20
+ .btn data-css='main_reverse' = icon('align-right')
21
+
15
22
  .btn-group.downloads
16
23
  = icon('download-alt')
17
- - %w(csv xls json).each do |format|
24
+ /- %w(csv xls json).each do |format|
25
+ - %w(csv xls).each do |format|
18
26
  - next if format == 'xls' && !defined?(Mime::XLSX)
19
27
  = link_to format, params.merge(format: format), id: "export_#{format}"
20
- a.btn.pull-right#columns_hider_show[href="#columns_hider" data-toggle='modal']= t 'admin.columns_hider.button'
21
-
@@ -1,7 +1,6 @@
1
1
  - if @breadcrumbs.present?
2
- ul.breadcrumb
3
- - @breadcrumbs[0..-2].each do |crumb|
4
- li
5
- = link_to crumb[:name], crumb[:url], crumb[:options]
6
- span.divider &nbsp;/&nbsp;
7
- li.active= link_to @breadcrumbs.last[:name], @breadcrumbs.last[:url], @breadcrumbs.last[:options]
2
+ - @breadcrumbs[0..-2].each do |crumb|
3
+ li
4
+ = link_to crumb[:name], crumb[:url], crumb[:options]
5
+ span.divider &nbsp;/&nbsp;
6
+ li.active= link_to [@breadcrumbs.last[:name] || @breadcrumbs.last[:url], @page_title].join(' - '), @breadcrumbs.last[:url], @breadcrumbs.last[:options]
@@ -0,0 +1,3 @@
1
+ <% flash.each do |k, v| %>
2
+ flash("<%= j v %>", "<%= k %>");
3
+ <% end unless flash.empty? %>
@@ -0,0 +1,14 @@
1
+ - attr_ids_method = "#{attribute_name.to_s.singularize}_ids"
2
+ - attr_ids = f.object.send(attr_ids_method)
3
+ - attr_name = "#{f.object_name}[#{attr_ids_method}][]"
4
+ - opts = reflection.options.slice(:conditions, :order)
5
+
6
+ - reflection.klass.roots.all(opts).each do |root|
7
+ .checkbox_tree_input
8
+ label.checkbox
9
+ = check_box_tag attr_name, root.id, attr_ids.include?(root.id)
10
+ b= AbAdmin.display_name(root)
11
+ - root.children.all(opts).each do |child|
12
+ label.checkbox
13
+ = check_box_tag attr_name, child.id, attr_ids.include?(child.id)
14
+ = AbAdmin.display_name(child)
@@ -1,7 +1,7 @@
1
1
  = admin_form_for @structure do |f|
2
2
  = f.locale_tabs do |l|
3
3
  = f.input :title, locale: l
4
- = f.input :redirect_url, locale: l
4
+ = f.input :redirect_url, locale: l, as: :string
5
5
 
6
6
  = f.input :slug
7
7
  - if @structure.moveable?
@@ -11,9 +11,12 @@
11
11
 
12
12
  = f.input :is_visible
13
13
 
14
- = input_set t('admin.pictures') do
14
+ = input_set ha(:picture) do
15
15
  = f.attach_file_field :picture, file_max_size: 2
16
16
 
17
+ = input_set ha(:pictures) do
18
+ = f.attach_file_field :pictures, file_max_size: 2
19
+
17
20
  = input_set t('admin.keywords') do
18
21
  = render 'admin/headers/form', f: f
19
22
 
@@ -5,6 +5,7 @@ footer
5
5
  = cache [I18n.locale, 'admin', 'footer'] do
6
6
  = render 'admin/fileupload/tmpl'
7
7
  = render 'admin/fileupload/ftmpl'
8
+ = render 'admin/fileupload/vtmpl'
8
9
  = render 'admin/shared/columns_hider'
9
10
 
10
11
  - unless admin?
@@ -20,11 +20,9 @@ header.navbar
20
20
  li.divider
21
21
  li= link_to(t('admin.auth.sign_out'), destroy_user_session_path, method: 'delete')
22
22
 
23
- = render 'admin/shared/breadcrumbs'
23
+ ul.breadcrumb
24
+ li.resource_actions
25
+ - action_items.each do |act|
26
+ = action_link(act)
27
+ = render 'admin/shared/breadcrumbs'
24
28
 
25
- .top_bar.clearfix
26
- .resource_actions
27
- - action_items.each do |act|
28
- = action_link(act)
29
- .resource_title
30
- h1= @page_title
@@ -17,8 +17,8 @@ html id="controller_#{controller_name}"
17
17
  = render 'layouts/admin/navigation'
18
18
  #main role="main"
19
19
  .container-fluid
20
+ = render('admin/shared/flash', flash: flash) if flash
20
21
  #container.row-fluid
21
- = render('admin/shared/flash', flash: flash) if flash
22
22
  .wrap_content
23
23
  .clearfix[data-pjax-container=true class=layout_css]= yield
24
24
  - if collection_action? && settings[:search]
@@ -197,14 +197,8 @@ en:
197
197
  deleted: Removed
198
198
  pending: Inactive
199
199
  suspended: Frozen
200
- versions:
201
- current: "The current version of"
202
- item: Element
203
- modified_at: "Date of editing"
204
- modified_by: "Edited (a)"
205
- title: Story
206
- type: Type
207
200
  admin_js:
201
+ empty: Empty
208
202
  add_link: Create?
209
203
  button_description: Description
210
204
  button_name_add: Add
@@ -295,8 +289,8 @@ en:
295
289
  updating: "Update ..."
296
290
  "yes": "Yes"
297
291
  will_paginate:
298
- next_label: "Next. →"
299
292
  page_gap: "..."
300
- pagination_info: "Displaying <b>%{from}&nbsp;-&nbsp;%{to}</b> of %{count} total"
293
+ pagination_info: "<b>%{from}&nbsp;-&nbsp;%{to}</b> of <b>%{count}</b>"
301
294
  pagination_info_empty: "0 total"
302
- previous_label: "← Prev."
295
+ next_label: ""
296
+ previous_label: "←"
@@ -211,14 +211,7 @@ it:
211
211
  deleted: Rimosso
212
212
  pending: Inattivo
213
213
  suspended: Congelato
214
- versions:
215
- current: La versione corrente di
216
- item: Elemento
217
- modified_at: Data di modifica
218
- modified_by: Edited (a)
219
- title: Storia
220
- type: Tipo
221
- admin_js:
214
+ admin_js:
222
215
  add_link: Crea?
223
216
  button_description: Descrizione
224
217
  button_name_add: Aggiungere
@@ -188,13 +188,6 @@ ru:
188
188
  deleted: "Удален"
189
189
  pending: "Неактивирован"
190
190
  suspended: "Заморожен"
191
- versions:
192
- current: "Текущая версия"
193
- item: "Элемент"
194
- modified_at: "Дата редактирования"
195
- modified_by: "Редактировал(а)"
196
- title: "История"
197
- type: "Тип"
198
191
  structure:
199
192
  kind:
200
193
  group: "Группа страницек"
@@ -207,6 +200,7 @@ ru:
207
200
  default: "По умолчанию"
208
201
  menu: "Меню"
209
202
  admin_js:
203
+ empty: Пусто
210
204
  add_link: "Создать?"
211
205
  button_description: "Описание"
212
206
  button_name_add: "Добавить"
@@ -290,11 +284,11 @@ ru:
290
284
  updating: "Обновление..."
291
285
  "yes": "Да"
292
286
  will_paginate:
293
- next_label: "След. &#8594;"
294
287
  page_gap: "&hellip;"
295
- pagination_info: "Показано <b>%{from}&nbsp;-&nbsp;%{to}</b> из <b>%{count}</b> всего"
288
+ pagination_info: "<b>%{from}&nbsp;-&nbsp;%{to}</b> из <b>%{count}</b>"
296
289
  pagination_info_empty: "0 всего"
297
- previous_label: "&#8592; Пред."
290
+ next_label: ""
291
+ previous_label: "←"
298
292
 
299
293
  errors:
300
294
  messages:
@@ -28,12 +28,12 @@ Feature: Export
28
28
  And should see "$234"
29
29
  And should see "Chair"
30
30
 
31
- Scenario: Export to json format
32
- When I am on the admin products page
33
- And I follow "export_json"
34
- Then should see "t-12"
35
- And should see "234"
36
- And should see "Chair"
31
+ # Scenario: Export to json format
32
+ # When I am on the admin products page
33
+ # And I follow "export_json"
34
+ # Then should see "t-12"
35
+ # And should see "234"
36
+ # And should see "Chair"
37
37
 
38
38
  Scenario: Export to xls format
39
39
  When I am on the admin products page
@@ -10,17 +10,17 @@ module AbAdmin
10
10
 
11
11
  module ClassMethods
12
12
  def max_time
13
- Rails.cache.fetch("by_class_#{name}", expires_in: 60) { maximum(:updated_at).to_i }
13
+ Rails.cache.fetch("by_class_#{name}", expires_in: 60) { unscoped.maximum(:updated_at).to_i }
14
14
  end
15
15
 
16
16
  def max_time_by_scope(scope)
17
- Rails.cache.fetch("by_class_#{name}_#{scope}", expires_in: 60) { send(scope).maximum(:updated_at).to_i }
17
+ Rails.cache.fetch("by_class_#{name}_#{scope}", expires_in: 60) { unscoped.send(scope).maximum(:updated_at).to_i }
18
18
  end
19
19
 
20
20
  def full_truncate
21
21
  destroy_all
22
22
  truncate!
23
- const_get(:Translation).truncate! if translates?
23
+ const_get(:Translation).truncate! if respond_to?(:translates?) && translates?
24
24
  end
25
25
 
26
26
  def all_ids