admin_bits 0.4.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 (68) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +20 -0
  3. data/LICENSE +165 -0
  4. data/README.md +19 -0
  5. data/Rakefile +33 -0
  6. data/lib/admin_bits.rb +50 -0
  7. data/lib/admin_bits/admin_resource.rb +96 -0
  8. data/lib/admin_bits/admin_resource/paginator.rb +14 -0
  9. data/lib/admin_bits/admin_resource/path_handler.rb +34 -0
  10. data/lib/admin_bits/base_config.rb +38 -0
  11. data/lib/admin_bits/engine.rb +4 -0
  12. data/lib/admin_bits/helpers.rb +44 -0
  13. data/lib/admin_bits/scopes.rb +52 -0
  14. data/lib/admin_bits/utils.rb +16 -0
  15. data/lib/generators/admin_bits_generator.rb +52 -0
  16. data/lib/generators/templates/controller.rb.erb +35 -0
  17. data/lib/generators/templates/index.html.erb +0 -0
  18. data/lib/generators/templates/layout.html.erb +3 -0
  19. data/test/admin_bits_test.rb +7 -0
  20. data/test/dummy/Rakefile +7 -0
  21. data/test/dummy/app/assets/stylesheets/admin_bits.css +0 -0
  22. data/test/dummy/app/controllers/admin/items_controller.rb +40 -0
  23. data/test/dummy/app/controllers/application_controller.rb +3 -0
  24. data/test/dummy/app/helpers/application_helper.rb +2 -0
  25. data/test/dummy/app/models/basic_admin_panel.rb +65 -0
  26. data/test/dummy/app/models/item.rb +7 -0
  27. data/test/dummy/app/views/admin/items/index.html.erb +30 -0
  28. data/test/dummy/app/views/admin_bits_modules/basic_admin_panel/edit.html.erb +4 -0
  29. data/test/dummy/app/views/admin_bits_modules/basic_admin_panel/index.html.erb +30 -0
  30. data/test/dummy/app/views/layouts/admin_bits_modules/basic_admin_panel/layout.html.erb +13 -0
  31. data/test/dummy/config.ru +4 -0
  32. data/test/dummy/config/application.rb +45 -0
  33. data/test/dummy/config/boot.rb +10 -0
  34. data/test/dummy/config/database.yml +22 -0
  35. data/test/dummy/config/environment.rb +5 -0
  36. data/test/dummy/config/environments/development.rb +27 -0
  37. data/test/dummy/config/environments/production.rb +50 -0
  38. data/test/dummy/config/environments/test.rb +36 -0
  39. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  40. data/test/dummy/config/initializers/inflections.rb +10 -0
  41. data/test/dummy/config/initializers/mime_types.rb +5 -0
  42. data/test/dummy/config/initializers/secret_token.rb +7 -0
  43. data/test/dummy/config/initializers/session_store.rb +8 -0
  44. data/test/dummy/config/locales/en.yml +5 -0
  45. data/test/dummy/config/routes.rb +57 -0
  46. data/test/dummy/db/development.sqlite3 +0 -0
  47. data/test/dummy/db/migrate/20131110141830_create_items.rb +15 -0
  48. data/test/dummy/db/schema.rb +25 -0
  49. data/test/dummy/db/test.sqlite3 +0 -0
  50. data/test/dummy/log/development.log +2368 -0
  51. data/test/dummy/log/test.log +672 -0
  52. data/test/dummy/public/404.html +26 -0
  53. data/test/dummy/public/422.html +26 -0
  54. data/test/dummy/public/500.html +26 -0
  55. data/test/dummy/public/favicon.ico +0 -0
  56. data/test/dummy/public/javascripts/application.js +2 -0
  57. data/test/dummy/public/javascripts/controls.js +965 -0
  58. data/test/dummy/public/javascripts/dragdrop.js +974 -0
  59. data/test/dummy/public/javascripts/effects.js +1123 -0
  60. data/test/dummy/public/javascripts/prototype.js +6001 -0
  61. data/test/dummy/public/javascripts/rails.js +202 -0
  62. data/test/dummy/script/rails +6 -0
  63. data/test/integration/ordering_test.rb +14 -0
  64. data/test/support/integration_case.rb +5 -0
  65. data/test/test_helper.rb +22 -0
  66. data/test/unit/path_handler_test.rb +17 -0
  67. data/test/unit/sorting_test.rb +49 -0
  68. metadata +123 -0
@@ -0,0 +1,202 @@
1
+ (function() {
2
+ Ajax.Responders.register({
3
+ onCreate: function(request) {
4
+ var token = $$('meta[name=csrf-token]')[0];
5
+ if (token) {
6
+ if (!request.options.requestHeaders) request.options.requestHeaders = {};
7
+ request.options.requestHeaders['X-CSRF-Token'] = token.readAttribute('content');
8
+ }
9
+ }
10
+ });
11
+
12
+ // Technique from Juriy Zaytsev
13
+ // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
14
+ function isEventSupported(eventName) {
15
+ var el = document.createElement('div');
16
+ eventName = 'on' + eventName;
17
+ var isSupported = (eventName in el);
18
+ if (!isSupported) {
19
+ el.setAttribute(eventName, 'return;');
20
+ isSupported = typeof el[eventName] == 'function';
21
+ }
22
+ el = null;
23
+ return isSupported;
24
+ }
25
+
26
+ function isForm(element) {
27
+ return Object.isElement(element) && element.nodeName.toUpperCase() == 'FORM';
28
+ }
29
+
30
+ function isInput(element) {
31
+ if (Object.isElement(element)) {
32
+ var name = element.nodeName.toUpperCase();
33
+ return name == 'INPUT' || name == 'SELECT' || name == 'TEXTAREA';
34
+ }
35
+ else return false;
36
+ }
37
+
38
+ var submitBubbles = isEventSupported('submit'),
39
+ changeBubbles = isEventSupported('change');
40
+
41
+ if (!submitBubbles || !changeBubbles) {
42
+ // augment the Event.Handler class to observe custom events when needed
43
+ Event.Handler.prototype.initialize = Event.Handler.prototype.initialize.wrap(
44
+ function(init, element, eventName, selector, callback) {
45
+ init(element, eventName, selector, callback);
46
+ // is the handler being attached to an element that doesn't support this event?
47
+ if ( (!submitBubbles && this.eventName == 'submit' && !isForm(this.element)) ||
48
+ (!changeBubbles && this.eventName == 'change' && !isInput(this.element)) ) {
49
+ // "submit" => "emulated:submit"
50
+ this.eventName = 'emulated:' + this.eventName;
51
+ }
52
+ }
53
+ );
54
+ }
55
+
56
+ if (!submitBubbles) {
57
+ // discover forms on the page by observing focus events which always bubble
58
+ document.on('focusin', 'form', function(focusEvent, form) {
59
+ // special handler for the real "submit" event (one-time operation)
60
+ if (!form.retrieve('emulated:submit')) {
61
+ form.on('submit', function(submitEvent) {
62
+ var emulated = form.fire('emulated:submit', submitEvent, true);
63
+ // if custom event received preventDefault, cancel the real one too
64
+ if (emulated.returnValue === false) submitEvent.preventDefault();
65
+ });
66
+ form.store('emulated:submit', true);
67
+ }
68
+ });
69
+ }
70
+
71
+ if (!changeBubbles) {
72
+ // discover form inputs on the page
73
+ document.on('focusin', 'input, select, textarea', function(focusEvent, input) {
74
+ // special handler for real "change" events
75
+ if (!input.retrieve('emulated:change')) {
76
+ input.on('change', function(changeEvent) {
77
+ input.fire('emulated:change', changeEvent, true);
78
+ });
79
+ input.store('emulated:change', true);
80
+ }
81
+ });
82
+ }
83
+
84
+ function handleRemote(element) {
85
+ var method, url, params;
86
+
87
+ var event = element.fire("ajax:before");
88
+ if (event.stopped) return false;
89
+
90
+ if (element.tagName.toLowerCase() === 'form') {
91
+ method = element.readAttribute('method') || 'post';
92
+ url = element.readAttribute('action');
93
+ // serialize the form with respect to the submit button that was pressed
94
+ params = element.serialize({ submit: element.retrieve('rails:submit-button') });
95
+ // clear the pressed submit button information
96
+ element.store('rails:submit-button', null);
97
+ } else {
98
+ method = element.readAttribute('data-method') || 'get';
99
+ url = element.readAttribute('href');
100
+ params = {};
101
+ }
102
+
103
+ new Ajax.Request(url, {
104
+ method: method,
105
+ parameters: params,
106
+ evalScripts: true,
107
+
108
+ onCreate: function(response) { element.fire("ajax:create", response); },
109
+ onComplete: function(response) { element.fire("ajax:complete", response); },
110
+ onSuccess: function(response) { element.fire("ajax:success", response); },
111
+ onFailure: function(response) { element.fire("ajax:failure", response); }
112
+ });
113
+
114
+ element.fire("ajax:after");
115
+ }
116
+
117
+ function insertHiddenField(form, name, value) {
118
+ form.insert(new Element('input', { type: 'hidden', name: name, value: value }));
119
+ }
120
+
121
+ function handleMethod(element) {
122
+ var method = element.readAttribute('data-method'),
123
+ url = element.readAttribute('href'),
124
+ csrf_param = $$('meta[name=csrf-param]')[0],
125
+ csrf_token = $$('meta[name=csrf-token]')[0];
126
+
127
+ var form = new Element('form', { method: "POST", action: url, style: "display: none;" });
128
+ $(element.parentNode).insert(form);
129
+
130
+ if (method !== 'post') {
131
+ insertHiddenField(form, '_method', method);
132
+ }
133
+
134
+ if (csrf_param) {
135
+ insertHiddenField(form, csrf_param.readAttribute('content'), csrf_token.readAttribute('content'));
136
+ }
137
+
138
+ form.submit();
139
+ }
140
+
141
+ function disableFormElements(form) {
142
+ form.select('input[type=submit][data-disable-with]').each(function(input) {
143
+ input.store('rails:original-value', input.getValue());
144
+ input.setValue(input.readAttribute('data-disable-with')).disable();
145
+ });
146
+ }
147
+
148
+ function enableFormElements(form) {
149
+ form.select('input[type=submit][data-disable-with]').each(function(input) {
150
+ input.setValue(input.retrieve('rails:original-value')).enable();
151
+ });
152
+ }
153
+
154
+ function allowAction(element) {
155
+ var message = element.readAttribute('data-confirm');
156
+ return !message || confirm(message);
157
+ }
158
+
159
+ document.on('click', 'a[data-confirm], a[data-remote], a[data-method]', function(event, link) {
160
+ if (!allowAction(link)) {
161
+ event.stop();
162
+ return false;
163
+ }
164
+
165
+ if (link.readAttribute('data-remote')) {
166
+ handleRemote(link);
167
+ event.stop();
168
+ } else if (link.readAttribute('data-method')) {
169
+ handleMethod(link);
170
+ event.stop();
171
+ }
172
+ });
173
+
174
+ document.on("click", "form input[type=submit], form button[type=submit], form button:not([type])", function(event, button) {
175
+ // register the pressed submit button
176
+ event.findElement('form').store('rails:submit-button', button.name || false);
177
+ });
178
+
179
+ document.on("submit", function(event) {
180
+ var form = event.findElement();
181
+
182
+ if (!allowAction(form)) {
183
+ event.stop();
184
+ return false;
185
+ }
186
+
187
+ if (form.readAttribute('data-remote')) {
188
+ handleRemote(form);
189
+ event.stop();
190
+ } else {
191
+ disableFormElements(form);
192
+ }
193
+ });
194
+
195
+ document.on('ajax:create', 'form', function(event, form) {
196
+ if (form == event.findElement()) disableFormElements(form);
197
+ });
198
+
199
+ document.on('ajax:complete', 'form', function(event, form) {
200
+ if (form == event.findElement()) enableFormElements(form);
201
+ });
202
+ })();
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
+
4
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
5
+ require File.expand_path('../../config/boot', __FILE__)
6
+ require 'rails/commands'
@@ -0,0 +1,14 @@
1
+ require 'test_helper'
2
+
3
+ class OrderingTest < ActiveSupport::IntegrationCase
4
+ test "I can see default DESC order on PRICE" do
5
+ visit admin_items_path
6
+ find(:css, "a.sort_desc", :text => "Total price")
7
+ end
8
+
9
+ test "I can easily change order" do
10
+ visit admin_items_path
11
+ click_link("Total price")
12
+ find(:css, "a.sort_asc", :text => "Total price")
13
+ end
14
+ end
@@ -0,0 +1,5 @@
1
+ # Define a bare test case to use with Capybara
2
+ class ActiveSupport::IntegrationCase < ActiveSupport::TestCase
3
+ include Capybara::DSL
4
+ include Rails.application.routes.url_helpers
5
+ end
@@ -0,0 +1,22 @@
1
+ # Configure Rails Envinronment
2
+ ENV["RAILS_ENV"] = "test"
3
+
4
+ require File.expand_path("../dummy/config/environment.rb", __FILE__)
5
+ require "rails/test_help"
6
+
7
+ ActionMailer::Base.delivery_method = :test
8
+ ActionMailer::Base.perform_deliveries = true
9
+ ActionMailer::Base.default_url_options[:host] = "test.com"
10
+
11
+ Rails.backtrace_cleaner.remove_silencers!
12
+
13
+ # Configure capybara for integration testing
14
+ require "capybara/rails"
15
+ Capybara.default_driver = :rack_test
16
+ Capybara.default_selector = :css
17
+
18
+ # Run any available migration
19
+ ActiveRecord::Migrator.migrate File.expand_path("../dummy/db/migrate/", __FILE__)
20
+
21
+ # Load support files
22
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
@@ -0,0 +1,17 @@
1
+ require 'test_helper'
2
+ require 'admin_bits/admin_resource/path_handler'
3
+
4
+ class PathHandlerTest < ActiveSupport::TestCase
5
+ test "path handler accepts procs with param-based route" do
6
+ routes = mock('Routes')
7
+ routes.expects(:admin_mega_path).with('some_id')
8
+
9
+ proc = Proc.new { |params| admin_mega_path(params[:obj_id]) }
10
+
11
+ handler = AdminBits::AdminResource::PathHandler.new(proc, {obj_id: 'some_id'})
12
+ handler.stubs(:routes).returns(routes)
13
+
14
+ handler.path
15
+ end
16
+ end
17
+
@@ -0,0 +1,49 @@
1
+ require 'test_helper'
2
+
3
+ class SortingTest < ActiveSupport::TestCase
4
+
5
+ def create_class_with_admin_bits(&block)
6
+ c = Class.new(ActionController::Base) do
7
+ include AdminBits
8
+
9
+ declare_resource :items, &block
10
+
11
+ # Stub
12
+ def params
13
+ @params ||= {}
14
+ end
15
+ end
16
+ c.new
17
+ end
18
+
19
+ test "there should be no default order specified, but it should still work" do
20
+ c = create_class_with_admin_bits do
21
+ path "/"
22
+ end
23
+ resource = c.admin_resource
24
+
25
+ assert_equal resource.get_order, nil
26
+ end
27
+
28
+ test "one can set order column & direction other than default" do
29
+ c = create_class_with_admin_bits do
30
+ ordering :name => "items.name"
31
+ path "/"
32
+ default_order :name
33
+ end
34
+ resource = c.admin_resource
35
+
36
+ assert_equal resource.get_order, "items.name DESC"
37
+ end
38
+
39
+ test "one can sort using multiple columns" do
40
+ c = create_class_with_admin_bits do
41
+ ordering :name => ["items.name", "items.id"]
42
+ path "/"
43
+ default_order :name
44
+ end
45
+ resource = c.admin_resource
46
+
47
+ assert_equal resource.get_order, "items.name DESC, items.id DESC"
48
+ end
49
+ end
metadata ADDED
@@ -0,0 +1,123 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: admin_bits
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0
5
+ platform: ruby
6
+ authors:
7
+ - Lukasz Pelszynski
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-12-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: kaminari
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: AdminBits simplifies creation of sortable / searchable lists found in
28
+ dashboards / admin panels
29
+ email: lpelszyn@o2.pl
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - lib/admin_bits/admin_resource.rb
35
+ - lib/admin_bits/admin_resource/paginator.rb
36
+ - lib/admin_bits/admin_resource/path_handler.rb
37
+ - lib/admin_bits/scopes.rb
38
+ - lib/admin_bits/helpers.rb
39
+ - lib/admin_bits/utils.rb
40
+ - lib/admin_bits/base_config.rb
41
+ - lib/admin_bits/engine.rb
42
+ - lib/admin_bits.rb
43
+ - lib/generators/templates/layout.html.erb
44
+ - lib/generators/templates/index.html.erb
45
+ - lib/generators/templates/controller.rb.erb
46
+ - lib/generators/admin_bits_generator.rb
47
+ - test/admin_bits_test.rb
48
+ - test/test_helper.rb
49
+ - test/unit/path_handler_test.rb
50
+ - test/unit/sorting_test.rb
51
+ - test/dummy/db/development.sqlite3
52
+ - test/dummy/db/test.sqlite3
53
+ - test/dummy/db/schema.rb
54
+ - test/dummy/db/migrate/20131110141830_create_items.rb
55
+ - test/dummy/config/environment.rb
56
+ - test/dummy/config/locales/en.yml
57
+ - test/dummy/config/database.yml
58
+ - test/dummy/config/environments/production.rb
59
+ - test/dummy/config/environments/development.rb
60
+ - test/dummy/config/environments/test.rb
61
+ - test/dummy/config/routes.rb
62
+ - test/dummy/config/initializers/session_store.rb
63
+ - test/dummy/config/initializers/secret_token.rb
64
+ - test/dummy/config/initializers/backtrace_silencers.rb
65
+ - test/dummy/config/initializers/inflections.rb
66
+ - test/dummy/config/initializers/mime_types.rb
67
+ - test/dummy/config/application.rb
68
+ - test/dummy/config/boot.rb
69
+ - test/dummy/script/rails
70
+ - test/dummy/config.ru
71
+ - test/dummy/Rakefile
72
+ - test/dummy/app/views/layouts/admin_bits_modules/basic_admin_panel/layout.html.erb
73
+ - test/dummy/app/views/admin_bits_modules/basic_admin_panel/edit.html.erb
74
+ - test/dummy/app/views/admin_bits_modules/basic_admin_panel/index.html.erb
75
+ - test/dummy/app/views/admin/items/index.html.erb
76
+ - test/dummy/app/helpers/application_helper.rb
77
+ - test/dummy/app/controllers/application_controller.rb
78
+ - test/dummy/app/controllers/admin/items_controller.rb
79
+ - test/dummy/app/assets/stylesheets/admin_bits.css
80
+ - test/dummy/app/models/basic_admin_panel.rb
81
+ - test/dummy/app/models/item.rb
82
+ - test/dummy/log/test.log
83
+ - test/dummy/log/development.log
84
+ - test/dummy/public/422.html
85
+ - test/dummy/public/500.html
86
+ - test/dummy/public/javascripts/prototype.js
87
+ - test/dummy/public/javascripts/rails.js
88
+ - test/dummy/public/javascripts/effects.js
89
+ - test/dummy/public/javascripts/controls.js
90
+ - test/dummy/public/javascripts/application.js
91
+ - test/dummy/public/javascripts/dragdrop.js
92
+ - test/dummy/public/404.html
93
+ - test/dummy/public/favicon.ico
94
+ - test/support/integration_case.rb
95
+ - test/integration/ordering_test.rb
96
+ - LICENSE
97
+ - Rakefile
98
+ - Gemfile
99
+ - README.md
100
+ homepage: https://github.com/bitmincer/admin_bits
101
+ licenses: []
102
+ metadata: {}
103
+ post_install_message:
104
+ rdoc_options: []
105
+ require_paths:
106
+ - lib
107
+ required_ruby_version: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - '>='
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ required_rubygems_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - '>='
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ requirements: []
118
+ rubyforge_project:
119
+ rubygems_version: 2.1.11
120
+ signing_key:
121
+ specification_version: 4
122
+ summary: AdminBits is a toolbox for custom dashboards
123
+ test_files: []