godmin 0.10.3 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +8 -0
  4. data/README.md +146 -81
  5. data/app/assets/javascripts/godmin/batch-actions.js +18 -13
  6. data/app/assets/stylesheets/godmin/index.css.scss +15 -8
  7. data/app/views/godmin/resource/_batch_actions.html.erb +2 -4
  8. data/app/views/godmin/resource/_breadcrumb.html.erb +0 -3
  9. data/app/views/godmin/resource/_button_actions.html.erb +2 -2
  10. data/app/views/godmin/resource/_filters.html.erb +17 -18
  11. data/app/views/godmin/resource/_form.html.erb +1 -1
  12. data/app/views/godmin/resource/_pagination.html.erb +11 -11
  13. data/app/views/godmin/resource/_scopes.html.erb +4 -4
  14. data/app/views/godmin/resource/_table.html.erb +30 -30
  15. data/app/views/godmin/resource/index.html.erb +3 -10
  16. data/godmin.gemspec +4 -1
  17. data/lib/generators/godmin/authentication/templates/sessions_controller.rb +1 -1
  18. data/lib/generators/godmin/install/install_generator.rb +1 -1
  19. data/lib/generators/godmin/resource/resource_generator.rb +4 -0
  20. data/lib/generators/godmin/resource/templates/resource_controller.rb +1 -9
  21. data/lib/generators/godmin/resource/templates/resource_service.rb +8 -0
  22. data/lib/godmin.rb +4 -2
  23. data/lib/godmin/{application.rb → application_controller.rb} +1 -1
  24. data/lib/godmin/authentication.rb +1 -1
  25. data/lib/godmin/authentication/{sessions.rb → sessions_controller.rb} +1 -1
  26. data/lib/godmin/authorization.rb +1 -1
  27. data/lib/godmin/authorization/policy_finder.rb +3 -1
  28. data/lib/godmin/helpers/application.rb +10 -0
  29. data/lib/godmin/helpers/batch_actions.rb +7 -4
  30. data/lib/godmin/helpers/filters.rb +72 -73
  31. data/lib/godmin/helpers/tables.rb +1 -3
  32. data/lib/godmin/paginator.rb +47 -0
  33. data/lib/godmin/rails.rb +1 -6
  34. data/lib/godmin/resolver.rb +7 -2
  35. data/lib/godmin/resources/resource_controller.rb +170 -0
  36. data/lib/godmin/resources/resource_service.rb +82 -0
  37. data/lib/godmin/resources/resource_service/batch_actions.rb +38 -0
  38. data/lib/godmin/resources/resource_service/filters.rb +37 -0
  39. data/lib/godmin/resources/resource_service/ordering.rb +27 -0
  40. data/lib/godmin/resources/resource_service/pagination.rb +22 -0
  41. data/lib/godmin/resources/resource_service/scopes.rb +61 -0
  42. data/lib/godmin/version.rb +1 -1
  43. data/test/dummy/config/environments/production.rb +1 -1
  44. data/test/dummy/config/environments/test.rb +1 -1
  45. data/test/dummy/db/schema.rb +16 -0
  46. data/test/lib/godmin/helpers/filters_test.rb +26 -0
  47. data/test/lib/godmin/paginator_test.rb +84 -0
  48. data/test/lib/godmin/policy_finder_test.rb +35 -6
  49. data/test/lib/godmin/resolver_test.rb +6 -0
  50. data/test/lib/godmin/resources/resource_service/batch_actions_test.rb +45 -0
  51. data/test/lib/godmin/resources/resource_service/filters_test.rb +32 -0
  52. data/test/lib/godmin/resources/resource_service/ordering_test.rb +37 -0
  53. data/test/lib/godmin/resources/resource_service/pagination_test.rb +31 -0
  54. data/test/lib/godmin/resources/resource_service/scopes_test.rb +57 -0
  55. data/test/lib/godmin/resources/resource_service_test.rb +21 -0
  56. data/test/test_helper.rb +62 -0
  57. metadata +75 -17
  58. data/.hound.yml +0 -3
  59. data/lib/godmin/resource.rb +0 -177
  60. data/lib/godmin/resource/batch_actions.rb +0 -45
  61. data/lib/godmin/resource/filters.rb +0 -41
  62. data/lib/godmin/resource/ordering.rb +0 -25
  63. data/lib/godmin/resource/pagination.rb +0 -64
  64. data/lib/godmin/resource/scopes.rb +0 -54
  65. data/test/dummy/db/test.sqlite3 +0 -0
@@ -1,23 +1,23 @@
1
1
  window.Godmin = window.Godmin || {};
2
2
 
3
3
  Godmin.BatchActions = (function() {
4
- var $form;
4
+ var $container;
5
5
  var $selectAll;
6
6
  var $selectNone;
7
7
 
8
8
  function initialize() {
9
- $form = $('form[data-behavior~=batch-actions-form]');
10
- $selectAll = $form.find('[data-behavior~=batch-actions-select-all]');
11
- $selectNone = $form.find('[data-behavior~=batch-actions-select-none]');
9
+ $container = $('[data-behavior~=batch-actions-container]');
10
+ $selectAll = $container.find('[data-behavior~=batch-actions-select-all]');
11
+ $selectNone = $container.find('[data-behavior~=batch-actions-select-none]');
12
12
 
13
13
  initializeEvents();
14
14
  initializeState();
15
15
  }
16
16
 
17
17
  function initializeEvents() {
18
- $form.find('[data-behavior~=batch-actions-select]').on('click', toggleCheckboxes);
19
- $form.find('[data-behavior~=batch-actions-checkbox]').on('change', toggleActions);
20
- $(document).delegate('[data-behavior~=batch-actions-action-link]', 'click', triggerAction);
18
+ $container.find('[data-behavior~=batch-actions-select]').on('click', toggleCheckboxes);
19
+ $container.find('[data-behavior~=batch-actions-checkbox]').on('change', toggleActions);
20
+ $(document).delegate('[data-behavior~=batch-actions-action-link]', 'mousedown', triggerAction);
21
21
  }
22
22
 
23
23
  function initializeState() {}
@@ -32,18 +32,24 @@ Godmin.BatchActions = (function() {
32
32
  $selectNone.removeClass('hidden');
33
33
  }
34
34
 
35
+ function checkedCheckboxes() {
36
+ return $container.find('[data-behavior~=batch-actions-checkbox]:checked').map(function() {
37
+ return this.id.match(/\d+/);
38
+ }).toArray().join(',');
39
+ }
40
+
35
41
  function toggleCheckboxes() {
36
- if ($form.find('[data-behavior~=batch-actions-checkbox]:checked').length > 0) {
37
- $form.find('[data-behavior~=batch-actions-checkbox]').prop('checked', false).trigger('change');
42
+ if (checkedCheckboxes().length > 0) {
43
+ $container.find('[data-behavior~=batch-actions-checkbox]').prop('checked', false).trigger('change');
38
44
  setSelectToAll();
39
45
  } else {
40
- $form.find('[data-behavior~=batch-actions-checkbox]').prop('checked', true).trigger('change');
46
+ $container.find('[data-behavior~=batch-actions-checkbox]').prop('checked', true).trigger('change');
41
47
  setSelectToNone();
42
48
  }
43
49
  }
44
50
 
45
51
  function toggleActions() {
46
- if ($form.find('[data-behavior~=batch-actions-checkbox]:checked').length) {
52
+ if (checkedCheckboxes().length) {
47
53
  $('[data-behavior~=batch-actions-action-link]').removeClass('hidden');
48
54
  setSelectToNone();
49
55
  } else {
@@ -53,8 +59,7 @@ Godmin.BatchActions = (function() {
53
59
  }
54
60
 
55
61
  function triggerAction() {
56
- $form.find('[data-behavior~=batch-actions-action]').val($(this).data('value'));
57
- $form.submit();
62
+ $(this).attr('href', $(this).attr('href') + '/' + checkedCheckboxes() + '?batch_action=' + $(this).data('value'));
58
63
  }
59
64
 
60
65
  return {
@@ -29,9 +29,18 @@ body {
29
29
  }
30
30
 
31
31
  #filters {
32
+ .filter .control-label {
33
+ display: block;
34
+ }
32
35
  .filter .form-control {
33
36
  min-width: 170px;
34
37
  }
38
+ .filter .form-control.selectize-control {
39
+ height: 34px;
40
+ }
41
+ .filter .form-control.selectize-control.single .item {
42
+ padding-right: 25px;
43
+ }
35
44
  }
36
45
 
37
46
  #actions {
@@ -43,6 +52,9 @@ body {
43
52
  td {
44
53
  vertical-align: middle;
45
54
  }
55
+ td .btn-group {
56
+ display: flex;
57
+ }
46
58
  }
47
59
 
48
60
  .pagination {
@@ -54,14 +66,9 @@ body {
54
66
  }
55
67
 
56
68
  .highlight {
69
+ -moz-animation: highlight 3s;
57
70
  -webkit-animation: highlight 3s;
58
71
  }
59
72
 
60
- @-webkit-keyframes highlight {
61
- from {
62
- background: #fffbcc;
63
- }
64
- to {
65
- background: none;
66
- }
67
- }
73
+ @-moz-keyframes highlight { from { background: #fffbcc; } to { background: none; } }
74
+ @-webkit-keyframes highlight { from { background: #fffbcc; } to { background: none; } }
@@ -1,14 +1,12 @@
1
- <% if batch_action_map.present? %>
1
+ <% if @resource_service.batch_action_map.present? %>
2
2
  <%= link_to translate_scoped("batch_actions.buttons.select_all"), "#", class: "btn btn-default",
3
3
  data: { behavior: "batch-actions-select batch-actions-select-all" } %>
4
4
  <%= link_to translate_scoped("batch_actions.buttons.deselect_all"), "#", class: "btn btn-default hidden",
5
5
  data: { behavior: "batch-actions-select batch-actions-select-none" } %>
6
6
 
7
7
  <div class="btn-group">
8
- <% batch_action_map.each do |name, options| %>
8
+ <% @resource_service.batch_action_map.each do |name, options| %>
9
9
  <%= batch_action_link(name, options) %>
10
10
  <% end %>
11
11
  </div>
12
-
13
- <%= hidden_field_tag "batch_action[action]", nil, data: { behavior: "batch-actions-action" } %>
14
12
  <% end %>
@@ -7,9 +7,6 @@
7
7
  <li>
8
8
  <%= link_to @resource_class.model_name.human(count: 2), @resource_class %>
9
9
  </li>
10
- <% end %>
11
- </li>
12
- <% unless index %>
13
10
  <li class="active">
14
11
  <% if @resource.new_record? %>
15
12
  <%= t("helpers.submit.create", model: @resource_class.model_name.human) %>
@@ -1,3 +1,3 @@
1
- <% if policy(@resources).create? %>
2
- <%= link_to t("helpers.submit.create", model: @resource_class.model_name.human), [:new, @resource_class.to_s.underscore], class: "btn btn-default" %>
1
+ <% if policy(@resource_service.build_resource({})).new? %>
2
+ <%= link_to t("helpers.submit.create", model: @resource_class.model_name.human), [:new, @resource_class.model_name.singular_route_key], class: "btn btn-default" %>
3
3
  <% end %>
@@ -1,23 +1,22 @@
1
- <div id="filters" class="panel panel-default">
2
- <div class="panel-body">
3
- <%= form_tag params, method: :get, class: "form-inline" do %>
1
+ <% if @resource_service.filter_map.present? %>
2
+ <div id="filters" class="panel panel-default">
3
+ <div class="panel-body">
4
+ <%= filter_form do |f| %>
5
+ <%= f.hidden_field :scope, value: params[:scope] %>
6
+ <%= f.hidden_field :order, value: params[:order] %>
4
7
 
5
- <%= hidden_field_tag :scope, nil, value: params[:scope] %>
6
- <%= hidden_field_tag :order, nil, value: params[:order] %>
8
+ <% @resource_service.filter_map.each do |name, options| %>
9
+ <%= partial_override "filters/#{name}", f: f, name: name, options: options do %>
10
+ <%= f.filter_field(name, options) %>
11
+ <% end %>
12
+ <% end %>
7
13
 
8
- <% filter_map.each do |name, options| %>
9
- <div class="filter form-group">
10
- <%= label_tag name, translate_scoped("filters.labels.#{name}", default: name.to_s.titleize) %><br>
11
- <%= filter_input_tag name, options %>
14
+ <div class="form-group pull-right">
15
+ <label class="control-label">&nbsp;</label><br>
16
+ <%= f.apply_filters_button %>
17
+ <%= f.clear_filters_button %>
12
18
  </div>
13
19
  <% end %>
14
-
15
- <div class="pull-right">
16
- <label>&nbsp;</label><br>
17
- <%= button_tag translate_scoped("filters.buttons.apply"), class: "btn btn-default" %>
18
- <%= link_to translate_scoped("filters.buttons.clear"), polymorphic_path(@resource_class, scope: params[:scope], order: params[:order]), class: "btn btn-default" %>
19
- </div>
20
-
21
- <% end %>
20
+ </div>
22
21
  </div>
23
- </div>
22
+ <% end %>
@@ -1,5 +1,5 @@
1
1
  <%= form_for @resource do |f| %>
2
- <% attrs_for_form.each do |attribute| %>
2
+ <% @resource_service.attrs_for_form.each do |attribute| %>
3
3
  <% if f.object.class.reflect_on_association(attribute) %>
4
4
  <%= f.association attribute %>
5
5
  <% else %>
@@ -1,25 +1,25 @@
1
1
  <div class="pull-left">
2
- <% if total_pages > 1 %>
2
+ <% if @resource_service.paginator.total_pages > 1 %>
3
3
  <nav>
4
4
  <ul class="pagination">
5
- <% unless pages.first == 1 && current_page == pages.first %>
5
+ <% unless @resource_service.paginator.pages.first == 1 && @resource_service.paginator.current_page == @resource_service.paginator.pages.first %>
6
6
  <li><%= link_to translate_scoped("pagination.first"), params.merge(page: 1) %></li>
7
- <li><%= link_to "«", params.merge(page: current_page - 1) %></li>
7
+ <li><%= link_to "«", params.merge(page: @resource_service.paginator.current_page - 1) %></li>
8
8
  <% end %>
9
- <% unless pages.first == 1 %>
9
+ <% unless @resource_service.paginator.pages.first == 1 %>
10
10
  <li class="disabled"><%= link_to "…" %></li>
11
11
  <% end %>
12
- <% pages.each do |page| %>
13
- <li class="<%= "active" if page == current_page %>">
12
+ <% @resource_service.paginator.pages.each do |page| %>
13
+ <li class="<%= "active" if page == @resource_service.paginator.current_page %>">
14
14
  <%= link_to page, params.merge(page: page) %>
15
15
  </li>
16
16
  <% end %>
17
- <% unless pages.last == total_pages %>
17
+ <% unless @resource_service.paginator.pages.last == @resource_service.paginator.total_pages %>
18
18
  <li class="disabled"><%= link_to "…" %></li>
19
19
  <% end %>
20
- <% unless pages.last == total_pages && current_page == pages.last %>
21
- <li><%= link_to "»", params.merge(page: current_page + 1) %></li>
22
- <li><%= link_to translate_scoped("pagination.last"), params.merge(page: total_pages) %></li>
20
+ <% unless @resource_service.paginator.pages.last == @resource_service.paginator.total_pages && @resource_service.paginator.current_page == @resource_service.paginator.pages.last %>
21
+ <li><%= link_to "»", params.merge(page: @resource_service.paginator.current_page + 1) %></li>
22
+ <li><%= link_to translate_scoped("pagination.last"), params.merge(page: @resource_service.paginator.total_pages) %></li>
23
23
  <% end %>
24
24
  </ul>
25
25
  </nav>
@@ -34,7 +34,7 @@
34
34
  <%= translate_scoped("pagination.entries.other", {
35
35
  resource: @resource_class.model_name.human(count: @resources.length).downcase,
36
36
  count: @resources.length,
37
- total: total_resources
37
+ total: @resource_service.paginator.total_resources
38
38
  }) %>
39
39
  <% end %>
40
40
  </div>
@@ -1,11 +1,11 @@
1
- <% unless scope_map.empty? %>
1
+ <% unless @resource_service.scope_map.empty? %>
2
2
  <div id="scopes">
3
3
  <ul class="nav nav-tabs">
4
- <% scope_map.each do |name, options| %>
5
- <li class="<%= "active" if params[:scope] == name.to_s %>">
4
+ <% @resource_service.scope_map.each do |name, options| %>
5
+ <li class="<%= "active" if @resource_service.scoped_by?(name) %>">
6
6
  <%= link_to url_for(params.merge(scope: name, only_path: true).except(:page)) do %>
7
7
  <%= translate_scoped("scopes.labels.#{name.to_s.underscore}", default: name.to_s.titleize) %>
8
- <span class="text-muted"> (<%= scope_count(name) %>)</span>
8
+ <span class="text-muted"> (<%= @resource_service.scope_count(name) %>)</span>
9
9
  <% end %>
10
10
  </li>
11
11
  <% end %>
@@ -1,37 +1,37 @@
1
1
  <div id="table" class="table-responsive">
2
2
  <table class="table table-bordered table-hover">
3
- <tr>
4
- <% if batch_action_map.present? %>
5
- <th></th>
6
- <% end %>
7
- <% attrs_for_index.each do |attr| %>
8
- <th>
9
- <%= column_header attr %>
10
- </th>
11
- <% end %>
12
- <th></th>
13
- </tr>
14
- <% @resources.each do |resource| %>
15
- <% if flash[:batch_actioned_ids] && flash[:batch_actioned_ids].include?(resource.id) %>
16
- <tr class="highlight">
17
- <% else %>
18
- <tr>
19
- <% end %>
20
- <% if batch_action_map.present? %>
21
- <td align="center">
22
- <%= check_box_tag "batch_action[items][#{resource.id}]", nil, nil,
23
- data: { behavior: "batch-actions-checkbox" } %>
24
- </td>
3
+ <thead>
4
+ <tr>
5
+ <% if @resource_service.batch_action_map.present? %>
6
+ <th></th>
25
7
  <% end %>
26
- <% attrs_for_index.each do |attr| %>
27
- <td>
28
- <%= column_value(resource, attr) %>
29
- </td>
8
+ <% @resource_service.attrs_for_index.each do |attr| %>
9
+ <th>
10
+ <%= column_header attr %>
11
+ </th>
30
12
  <% end %>
31
- <td>
32
- <%= render partial: "columns/actions", locals: { resource: resource } %>
33
- </td>
13
+ <th></th>
34
14
  </tr>
35
- <% end %>
15
+ </thead>
16
+ <tbody>
17
+ <% @resources.each do |resource| %>
18
+ <tr data-resource-id="<%= resource.id %>" class="<%= "highlight" if flash[:updated_ids] && flash[:updated_ids].include?(resource.id) %>">
19
+ <% if @resource_service.batch_action_map.present? %>
20
+ <td align="center">
21
+ <%= check_box_tag "batch_action[items][#{resource.id}]", nil, nil,
22
+ data: { behavior: "batch-actions-checkbox" } %>
23
+ </td>
24
+ <% end %>
25
+ <% @resource_service.attrs_for_index.each do |attr| %>
26
+ <td>
27
+ <%= column_value(resource, attr) %>
28
+ </td>
29
+ <% end %>
30
+ <td>
31
+ <%= render partial: "columns/actions", locals: { resource: resource } %>
32
+ </td>
33
+ </tr>
34
+ <% end %>
35
+ </tbody>
36
36
  </table>
37
37
  </div>
@@ -1,17 +1,10 @@
1
1
  <%= render partial: "breadcrumb", locals: { index: true } %>
2
-
3
2
  <%= render partial: "scopes" %>
3
+ <%= render partial: "filters" %>
4
4
 
5
- <% if filter_map.present? %>
6
- <%= render partial: "filters" %>
7
- <% end %>
8
-
9
- <%= form_tag [:batch_action, @resource_class], data: { behavior: "batch-actions-form" } do %>
10
-
5
+ <div data-behavior="batch-actions-container">
11
6
  <%= render partial: "actions" %>
12
-
13
7
  <%= render partial: "table" %>
14
-
15
- <% end %>
8
+ </div>
16
9
 
17
10
  <%= render partial: "pagination" %>
data/godmin.gemspec CHANGED
@@ -26,7 +26,10 @@ Gem::Specification.new do |gem|
26
26
  gem.add_dependency "momentjs-rails", ">= 2.8.1"
27
27
  gem.add_dependency "rails", "~> 4.0"
28
28
  gem.add_dependency "sass-rails", ">= 4.0"
29
- gem.add_dependency "selectize-rails", "~> 0.11.2"
29
+ gem.add_dependency "selectize-rails", "~> 0.12.0"
30
30
 
31
31
  gem.add_development_dependency "sqlite3"
32
+ gem.add_development_dependency "minitest"
33
+ gem.add_development_dependency "minitest-reporters"
34
+ gem.add_development_dependency "pry"
32
35
  end
@@ -4,6 +4,6 @@ require_dependency "<%= File.join(namespaced_path, "application_controller") %>"
4
4
  <% end -%>
5
5
  <% module_namespacing do -%>
6
6
  class SessionsController < ApplicationController
7
- include Godmin::Authentication::Sessions
7
+ include Godmin::Authentication::SessionsController
8
8
  end
9
9
  <% end -%>
@@ -23,7 +23,7 @@ class Godmin::InstallGenerator < Godmin::Generators::Base
23
23
  def modify_application_controller
24
24
  inject_into_file File.join("app/controllers", namespaced_path, "application_controller.rb"), after: "ActionController::Base\n" do
25
25
  <<-END.strip_heredoc.indent(namespace ? 4 : 2)
26
- include Godmin::Application
26
+ include Godmin::ApplicationController
27
27
  END
28
28
  end
29
29
  end
@@ -14,4 +14,8 @@ class Godmin::ResourceGenerator < Godmin::Generators::NamedBase
14
14
  def create_controller
15
15
  template "resource_controller.rb", File.join("app/controllers", class_path, "#{file_name.pluralize}_controller.rb")
16
16
  end
17
+
18
+ def create_service
19
+ template "resource_service.rb", File.join("app/services", class_path, "#{file_name}_service.rb")
20
+ end
17
21
  end
@@ -4,14 +4,6 @@ require_dependency "<%= File.join(namespaced_path, "application_controller") %>"
4
4
  <% end -%>
5
5
  <% module_namespacing do -%>
6
6
  class <%= class_name.pluralize %>Controller < ApplicationController
7
- include Godmin::Resource
8
-
9
- def attrs_for_index
10
- <%= @attributes.map(&:to_sym) %>
11
- end
12
-
13
- def attrs_for_form
14
- <%= @attributes.map(&:to_sym) %>
15
- end
7
+ include Godmin::Resources::ResourceController
16
8
  end
17
9
  <% end -%>
@@ -0,0 +1,8 @@
1
+ <% module_namespacing do -%>
2
+ class <%= class_name %>Service
3
+ include Godmin::Resources::ResourceService
4
+
5
+ attrs_for_index <%= @attributes.map { |x| ":#{x}" }.join(", ") %>
6
+ attrs_for_form <%= @attributes.map { |x| ":#{x}" }.join(", ") %>
7
+ end
8
+ <% end -%>
data/lib/godmin.rb CHANGED
@@ -2,13 +2,15 @@ require "bootstrap-sass"
2
2
  require "bootstrap_form"
3
3
  require "momentjs-rails"
4
4
  require "selectize-rails"
5
- require "godmin/application"
5
+ require "godmin/application_controller"
6
6
  require "godmin/authentication"
7
7
  require "godmin/authorization"
8
8
  require "godmin/engine"
9
+ require "godmin/paginator"
9
10
  require "godmin/rails"
10
11
  require "godmin/resolver"
11
- require "godmin/resource"
12
+ require "godmin/resources/resource_controller"
13
+ require "godmin/resources/resource_service"
12
14
  require "godmin/version"
13
15
 
14
16
  module Godmin
@@ -3,7 +3,7 @@ require "godmin/helpers/forms"
3
3
  require "godmin/helpers/translations"
4
4
 
5
5
  module Godmin
6
- module Application
6
+ module ApplicationController
7
7
  extend ActiveSupport::Concern
8
8
 
9
9
  included do