godmin 0.10.3 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
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