adminpanel 2.4.3 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -0
  3. data/README.md +16 -16
  4. data/adminpanel.gemspec +9 -8
  5. data/app/assets/javascripts/adminpanel/application.js +4 -0
  6. data/app/assets/javascripts/adminpanel/bootstrap-wysihtml5.js +2 -4
  7. data/app/assets/javascripts/adminpanel/sortable.js.coffee +27 -0
  8. data/app/assets/stylesheets/adminpanel/application.css +1 -0
  9. data/app/assets/stylesheets/adminpanel/sortable.css.scss.erb +13 -0
  10. data/app/controllers/adminpanel/application_controller.rb +0 -1
  11. data/app/controllers/adminpanel/sessions_controller.rb +5 -2
  12. data/app/controllers/concerns/adminpanel/rest_actions.rb +24 -22
  13. data/app/controllers/concerns/adminpanel/sortable_actions.rb +3 -20
  14. data/app/helpers/adminpanel/breadcrumbs_helper.rb +6 -5
  15. data/app/helpers/adminpanel/router_helper.rb +9 -3
  16. data/app/helpers/adminpanel/shared_pages_helper.rb +1 -1
  17. data/app/models/concerns/adminpanel/base.rb +34 -11
  18. data/app/models/concerns/adminpanel/sitemap.rb +0 -1
  19. data/app/models/concerns/adminpanel/sortable.rb +33 -30
  20. data/app/models/concerns/adminpanel/sortable_gallery.rb +90 -0
  21. data/app/views/adminpanel/form/_adminpanel_file_field.html.erb +1 -1
  22. data/app/views/adminpanel/templates/index.html.erb +41 -13
  23. data/app/views/adminpanel/templates/show.html.erb +33 -13
  24. data/config/initializers/adminpanel/carrierwave_mini_magick_quality.rb +11 -0
  25. data/config/locales/en.yml +3 -7
  26. data/config/locales/es.yml +1 -8
  27. data/config/routes.rb +6 -8
  28. data/lib/adminpanel.rb +9 -8
  29. data/lib/adminpanel/version.rb +1 -1
  30. data/lib/generators/adminpanel/custom_errors/custom_errors_generator.rb +37 -0
  31. data/lib/generators/adminpanel/custom_errors/templates/errors_controller.rb +14 -0
  32. data/lib/generators/adminpanel/custom_errors/templates/show.html.erb +1 -0
  33. data/lib/generators/adminpanel/gallery/templates/gallery_template.rb +8 -3
  34. data/lib/generators/adminpanel/gallery/templates/uploader.rb +4 -1
  35. data/lib/generators/adminpanel/initialize/initialize_generator.rb +0 -12
  36. data/lib/generators/adminpanel/initialize/templates/adminpanel_setup.rb +1 -2
  37. data/lib/generators/adminpanel/resource/resource_generator.rb +29 -8
  38. data/lib/generators/adminpanel/resource/resource_generator_helper.rb +34 -7
  39. data/lib/generators/adminpanel/resource/templates/adminpanel_resource_template.rb +7 -2
  40. data/lib/tasks/adminpanel/adminpanel.rake +19 -61
  41. data/test/dummy/app/models/adminpanel/file_resourcefile.rb +1 -1
  42. data/test/dummy/app/models/adminpanel/gallery.rb +9 -4
  43. data/test/dummy/app/models/adminpanel/galleryfile.rb +2 -2
  44. data/test/dummy/app/models/adminpanel/photo.rb +1 -1
  45. data/test/dummy/app/models/adminpanel/product.rb +0 -4
  46. data/test/dummy/config/initializers/adminpanel_setup.rb +1 -1
  47. data/test/dummy/test/fixtures/adminpanel/galleryfiles.yml +24 -0
  48. data/test/features/shared/concerns/sortable_gallery_ui_test.rb +25 -0
  49. data/test/features/shared/concerns/sortable_test.rb +4 -4
  50. data/test/features/shared/form/{belongs_to_non_category_modal_test.rb → belongs_to_remote_test.rb} +1 -1
  51. data/test/features/shared/form/{has_many_through_non_category_modal_test.rb → has_many_through_remote_test.rb} +1 -1
  52. data/test/generators/dump_generator_test.rb +1 -13
  53. data/test/generators/gallery_generator_test.rb +1 -1
  54. data/test/generators/initialize_generator_test.rb +1 -9
  55. data/test/generators/resource_generator_test.rb +21 -1
  56. data/test/helpers/router_helper_test.rb +0 -4
  57. data/test/models/adminpanel/sortable_gallery_unit_test.rb +118 -0
  58. data/test/models/adminpanel/sortable_unit_test.rb +75 -0
  59. data/test/tasks/adminpanel_rake_test.rb +1 -1
  60. metadata +86 -85
  61. data/app/assets/images/adminpanel/loguito.png +0 -0
  62. data/app/controllers/adminpanel/categories_controller.rb +0 -52
  63. data/app/controllers/concerns/adminpanel/galleryzable_actions.rb +0 -34
  64. data/app/models/concerns/adminpanel/galleryzation.rb +0 -78
  65. data/app/views/adminpanel/categories/_categories_table.html.erb +0 -48
  66. data/app/views/adminpanel/categories/_category_form.html.erb +0 -33
  67. data/app/views/adminpanel/categories/create.js.erb +0 -6
  68. data/app/views/adminpanel/categories/index.html.erb +0 -63
  69. data/app/views/adminpanel/categories/new.js.erb +0 -5
  70. data/app/views/adminpanel/icons/_move_to_better.html.erb +0 -17
  71. data/app/views/adminpanel/icons/_move_to_worst.html.erb +0 -18
  72. data/app/views/adminpanel/shared/_gallery_entries.html.erb +0 -11
  73. data/app/views/adminpanel/shared/_index_records.html.erb +0 -32
  74. data/app/views/adminpanel/templates/gallery_entries.js.erb +0 -1
  75. data/app/views/adminpanel/templates/index_records.js.erb +0 -1
  76. data/lib/generators/adminpanel/initialize/templates/category_template.rb +0 -45
  77. data/lib/generators/adminpanel/initialize/templates/create_adminpanel_categories_table.rb +0 -11
  78. data/test/features/categories/categories_index_test.rb +0 -31
  79. data/test/features/shared/concerns/galleryzable_test.rb +0 -22
  80. data/test/features/shared/form/belongs_to_category_modal_test.rb +0 -35
  81. data/test/features/shared/form/has_many_through_category_modal_test.rb +0 -35
  82. data/test/models/adminpanel/galleryzable_test.rb +0 -28
@@ -92,7 +92,7 @@ module Adminpanel
92
92
 
93
93
  def table_type(model)
94
94
  if model.is_sortable?
95
- ''
95
+ 'sortable'
96
96
  else
97
97
  'information-table'
98
98
  end
@@ -4,6 +4,8 @@ module Adminpanel
4
4
 
5
5
  # static(class) methods
6
6
  module ClassMethods
7
+
8
+ # API methods
7
9
  def mount_images(relation)
8
10
  has_many relation, dependent: :destroy
9
11
  accepts_nested_attributes_for relation, allow_destroy: true
@@ -14,6 +16,8 @@ module Adminpanel
14
16
  super(name, scope, options.reverse_merge!({touch: true}))
15
17
  end
16
18
 
19
+ # The fields and the types that should be used to generate form
20
+ # and display fields
17
21
  def form_attributes
18
22
  []
19
23
  end
@@ -24,6 +28,11 @@ module Adminpanel
24
28
  'please overwrite self.display_name'
25
29
  end
26
30
 
31
+ # side menu icon
32
+ def icon
33
+ 'truck'
34
+ end
35
+
27
36
  # The word that is going to be shown in the side menu, routes and
28
37
  # breadcrumb.
29
38
  def collection_name
@@ -41,6 +50,9 @@ module Adminpanel
41
50
  return "field #{field} 'label' property not found :("
42
51
  end
43
52
 
53
+ # returns the attributes that should be shown in the correspondin view
54
+ # (some attributes may be filtered from the index table, from the show
55
+ # or even both)
44
56
  def display_attributes(type)
45
57
  display_attributes = []
46
58
  form_attributes.each do |attribute|
@@ -57,11 +69,12 @@ module Adminpanel
57
69
  end
58
70
  end
59
71
  end
60
-
61
72
  return display_attributes
62
73
  end
63
74
 
64
- def has_images?
75
+ # return true if model has adminpanel_file_field in
76
+ # it's attributes
77
+ def has_gallery?
65
78
  form_attributes.each do |fields|
66
79
  fields.each do |attribute, properties|
67
80
  if properties['type'] == 'adminpanel_file_field'
@@ -72,7 +85,9 @@ module Adminpanel
72
85
  return false
73
86
  end
74
87
 
75
- def get_image_relationship
88
+ # returns the attribute that should be namespaced to be the class
89
+ # ex: returns 'productfiles', so class is Adminpanel::Productfile
90
+ def gallery_relationship
76
91
  form_attributes.each do |fields|
77
92
  fields.each do |attribute, properties|
78
93
  if properties['type'] == 'adminpanel_file_field'
@@ -83,6 +98,16 @@ module Adminpanel
83
98
  return false
84
99
  end
85
100
 
101
+ # gets the class gallery and return it's class
102
+ def gallery_class
103
+ "adminpanel/#{gallery_relationship}".classify.constantize
104
+ end
105
+
106
+ # returns all the class of the attributes of a given type.
107
+ # Usage:
108
+ # To get all classes of all belongs_to attributes:
109
+ # @model.relationships_of('belongs_to')
110
+ # # => ['Adminpanel::Category', Adminpanel::ModelBelongTo]
86
111
  def relationships_of(type_property)
87
112
  classes_of_relation = []
88
113
  form_attributes.each do |fields|
@@ -95,14 +120,6 @@ module Adminpanel
95
120
  return classes_of_relation
96
121
  end
97
122
 
98
- def icon
99
- 'truck'
100
- end
101
-
102
- def gallery_children
103
- nil
104
- end
105
-
106
123
  def routes_options
107
124
  { path: collection_name.parameterize }
108
125
  end
@@ -135,6 +152,12 @@ module Adminpanel
135
152
  false
136
153
  end
137
154
 
155
+ def has_sortable_gallery?
156
+ if has_gallery?
157
+ gallery_class.is_sortable?
158
+ end
159
+ end
160
+
138
161
  private
139
162
 
140
163
  def exclude?(route)
@@ -21,7 +21,6 @@ module Adminpanel
21
21
  logger.info Time.now
22
22
  ping_urls.each do |name, url|
23
23
  request = url % CGI.escape("#{root_url}/sitemap.xml")
24
- logger.info root_url
25
24
  logger.info " Pinging #{name} with #{request}"
26
25
  if !Rails.env.development?
27
26
  response = Net::HTTP.get_response(URI.parse(request))
@@ -6,58 +6,61 @@ module Adminpanel
6
6
  included do
7
7
  before_create :set_position
8
8
  before_destroy :rearrange_positions
9
-
10
- default_scope do
11
- order('position ASC')
12
- end
13
9
  end
14
10
 
15
11
  module ClassMethods
16
12
  def is_sortable?
17
13
  true
18
14
  end
19
- end
20
15
 
21
- def move_to_better_position
22
- if self.position > 1
23
- conflicting_gallery(self.position - 1).increment!(:position)
24
- self.decrement!(:position)
16
+ def ordered
17
+ order('position ASC')
18
+ end
25
19
 
26
- true
27
- else
28
- false
20
+ def in_better_position(current_position, new_position)
21
+ where(
22
+ 'position >= ? AND position < ?',
23
+ new_position,
24
+ current_position
25
+ )
26
+ end
27
+
28
+ def in_worst_position(current_position, new_position)
29
+ where(
30
+ 'position > ? AND position <= ?',
31
+ current_position,
32
+ new_position
33
+ )
29
34
  end
30
35
  end
31
36
 
32
- def move_to_worst_position
33
- records = self.class.count
34
- if self.position < records
35
- conflicting_gallery(self.position + 1).decrement!(:position)
36
- self.increment!(:position)
37
- true
37
+ def move_to_position(new_position)
38
+ if new_position < position
39
+ # search for better elements and downgrade them
40
+ self.class.in_better_position(
41
+ self.position,
42
+ new_position
43
+ ).update_all('position = position + 1')
38
44
  else
39
- false
45
+ # search for worster elements and upgrade them
46
+ self.class.in_worst_position(
47
+ self.position,
48
+ new_position
49
+ ).update_all('position = position - 1')
40
50
  end
51
+ self.update(position: new_position)
41
52
  end
42
53
 
43
54
  protected
44
- def conflicting_gallery(conflicting_position)
45
- logger.info "searching pos: #{conflicting_position}"
46
- self.class.find_by_position(conflicting_position)
47
- end
48
55
 
49
56
  def rearrange_positions
50
- unarranged_records = self.class.where(
57
+ self.class.where(
51
58
  'position > ?', self.position
52
- )
53
- unarranged_records.each do |record|
54
- record.update_attribute(:position, gallery.position - 1)
55
- end
56
-
59
+ ).update_all('position = position - 1')
57
60
  end
58
61
 
59
62
  def set_position
60
- last_record = self.class.last
63
+ last_record = self.class.ordered.last
61
64
  if last_record.nil?
62
65
  # this is the first record that is created
63
66
  self.position = 1
@@ -0,0 +1,90 @@
1
+ module Adminpanel
2
+ module SortableGallery
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ before_create :set_position
7
+ before_destroy :rearrange_positions
8
+
9
+ scope :ordered, -> { order('position ASC') }
10
+ end
11
+
12
+ module ClassMethods
13
+ def is_sortable?
14
+ true
15
+ end
16
+
17
+ def in_better_position(current_position, new_position, relation_id)
18
+ where(
19
+ 'position >= ? AND position < ?',
20
+ new_position,
21
+ current_position
22
+ ).where(
23
+ relation_field => relation_id
24
+ # => 'product_id' => member.product_id
25
+ )
26
+ end
27
+
28
+ def in_worst_position(current_position, new_position, relation_id)
29
+ where(
30
+ 'position > ? AND position <= ?',
31
+ current_position,
32
+ new_position
33
+ ).where(
34
+ relation_field => relation_id
35
+ # => 'product_id' => member.product_id
36
+ )
37
+ end
38
+ end
39
+
40
+ def move_to_position(new_position)
41
+ if new_position < position
42
+ # search for better elements and downgrade them
43
+ self.class.in_better_position(
44
+ self.position,
45
+ new_position,
46
+ self.send(self.class.relation_field)
47
+ ).update_all('position = position + 1')
48
+ else
49
+ # search for worster elements and upgrade them
50
+ self.class.in_worst_position(
51
+ self.position,
52
+ new_position,
53
+ self.send(self.class.relation_field)
54
+ ).update_all('position = position - 1')
55
+ end
56
+ self.update(position: new_position)
57
+ end
58
+
59
+ # we should detect if the name isn't defined in the class
60
+ def name
61
+ I18n.t('gallery.image')
62
+ end
63
+
64
+ protected
65
+
66
+ def rearrange_positions
67
+ self.class.where(
68
+ self.class.relation_field => self.send(
69
+ self.class.relation_field
70
+ )
71
+ ).where(
72
+ 'position > ?',
73
+ self.position
74
+ ).update_all('position = position - 1')
75
+ end
76
+
77
+ def set_position
78
+ last_record = self.class.where(
79
+ self.class.relation_field => self.send(
80
+ self.class.relation_field
81
+ )
82
+ ).ordered.last
83
+ if last_record.nil?
84
+ self.position = 1
85
+ else
86
+ self.position = last_record.position + 1
87
+ end
88
+ end
89
+ end
90
+ end
@@ -13,7 +13,7 @@
13
13
 
14
14
  <% if (
15
15
  properties['max-files'].to_i != 0 &&
16
- properties['max-files'].to_i <= f.object.send(@model.get_image_relationship).count.to_i
16
+ properties['max-files'].to_i <= f.object.send(@model.gallery_relationship).count.to_i
17
17
  ) %>
18
18
  <% hidden = 'hidden' %>
19
19
  <% else %>
@@ -15,27 +15,55 @@
15
15
  <table id="<%= table_type(@model) %>" class="table table-striped table-bordered dataTable">
16
16
  <thead><!-- model attributes -->
17
17
  <tr>
18
+ <% if @model.is_sortable? %>
19
+ <th></th>
20
+ <% end %>
18
21
  <% @model.display_attributes('index').each do |fields| %>
19
22
  <% fields.each do |attribute, properties| %>
20
23
  <th><%= properties['label'] %></th>
21
24
  <% end %>
22
25
  <% end %>
23
- <% if @model.is_sortable? %>
24
- <th>
25
- <%= I18n.t('position') %>
26
- </th>
27
- <% end %>
28
26
  <th><%= I18n.t('actions') %></th>
29
27
  </tr>
30
28
  </thead><!-- Ends model attributes -->
31
- <% if @collection != [] %>
32
- <% last_update = @collection.max_by(&:updated_at).updated_at %>
33
- <% end %>
34
- <% cache ["#{@model.name}-collection", last_update], skip_digest: true do %>
35
- <tbody id="body-content">
36
- <%= render 'adminpanel/shared/index_records', collection: @collection %>
37
- </tbody>
38
- <% end %><!-- end collection cache -->
29
+
30
+ <tbody id="<%= table_type(@model) %>">
31
+ <% @collection = @collection.ordered if table_type(@model) == 'sortable' %>
32
+ <% @collection.each do |member| %>
33
+ <% cache ["#{member.class}-member", member] do %>
34
+ <tr
35
+ data-id="<%= member.id %>"
36
+ <% if @model.is_sortable? %>
37
+ data-url="<%= url_for [:move_to_position, member] %>"
38
+ <% end %>
39
+ >
40
+ <% if @model.is_sortable? %>
41
+ <td class="draggable">
42
+ <i class="fa fa-bars"></i>
43
+ </td>
44
+ <% end %>
45
+ <% @model.display_attributes('index').each do |fields| %>
46
+ <% fields.each do |attribute, properties| %>
47
+ <td>
48
+ <%= field_value(properties, attribute, member) %>
49
+ </td>
50
+ <% end %>
51
+ <% end %>
52
+ <td>
53
+ <%= render 'adminpanel/icons/show', resource: member %>
54
+
55
+ <%= render 'adminpanel/icons/edit', resource: member %>
56
+
57
+ <%= render 'adminpanel/icons/delete', resource: member %>
58
+
59
+ <%= render 'adminpanel/icons/facebook', resource: member %>
60
+
61
+ <%= render 'adminpanel/icons/twitter', resource: member %>
62
+ </td>
63
+ </tr>
64
+ <% end %>
65
+ <% end %>
66
+ </tbody>
39
67
  </table>
40
68
  </div>
41
69
  </div>
@@ -44,32 +44,52 @@
44
44
  </div>
45
45
  </div>
46
46
 
47
- <% if @model.has_images? %>
47
+ <% if @model.has_gallery? %>
48
48
  <div class="widget widget-padding span6">
49
49
  <div class="widget-header">
50
50
  <%= content_tag(:i, nil, class: "fa fa-#{@model.icon}") %>
51
51
  <h5><%= I18n.t('gallery.container') %>: <%= @model.display_name.humanize %>
52
- <%= render 'adminpanel/icons/edit', resource: @resource_instance %>
52
+ <%= render 'adminpanel/icons/edit', resource: @resource_instance %>
53
53
  </h5>
54
54
  </div>
55
- <% if @model.gallery_children %>
55
+ <% if @model.has_sortable_gallery? %>
56
56
  <div class="widget-body widget-tasks-assigned clearfix">
57
- <ul id="gallery-entries">
58
- <%= render(
59
- 'adminpanel/shared/gallery_entries',
60
- images: @resource_instance.send(
61
- @model.get_image_relationship
62
- ).ordered
63
- ) %>
64
- </ul>
57
+ <table class="table table-striped table-bordered">
58
+ <thead>
59
+ <tr>
60
+ <td class="draggable-header"></td>
61
+ <td><i class="fa fa-picture-o"></i></td>
62
+ </tr>
63
+ </thead>
64
+ <tbody id="sortable">
65
+ <% collection = @resource_instance.send(@model.gallery_relationship).ordered %>
66
+ <% collection.each do |image| %>
67
+ <tr
68
+ data-id="<%= image.id %>"
69
+ data-url="<%= url_for [:move_to_position, image] %>"
70
+ >
71
+ <td class="draggable img"><i class="fa fa-bars fa-2x"></i></td>
72
+ <td>
73
+ <%= link_to(
74
+ image_tag(image.file_url(:thumb)),
75
+ image.file.to_s,
76
+ rel: "group",
77
+ name: @model.display_name
78
+ ) %>
79
+ </td>
80
+ </tr>
81
+ <% end %>
82
+ </tbody>
83
+ </table>
65
84
  </div>
66
85
  <% else %>
67
86
  <div class="widget-body row-fluid">
68
- <% @resource_instance.send(@model.get_image_relationship).each do |image|%>
87
+ <% @resource_instance.send(@model.gallery_relationship).each do |image|%>
69
88
  <%= link_to(
70
89
  image_tag( image.file_url(:thumb) ),
71
90
  image.file_url.to_s,
72
- rel: 'group', name: @model.display_name
91
+ rel: 'group',
92
+ name: @model.display_name
73
93
  ) %>
74
94
  <% end %>
75
95
  </div>