active_admin-sortable_tree 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.travis.yml +8 -0
  4. data/Gemfile +10 -0
  5. data/MIT-LICENSE +20 -0
  6. data/README.md +163 -0
  7. data/Rakefile +57 -0
  8. data/active_admin-sortable_tree.gemspec +30 -0
  9. data/app/assets/javascripts/active_admin/sortable.js.coffee +91 -0
  10. data/app/assets/stylesheets/active_admin/sortable.css.sass +79 -0
  11. data/bin/rails +11 -0
  12. data/gemfiles/3.2.gemfile +7 -0
  13. data/gemfiles/4.0.gemfile +10 -0
  14. data/lib/active_admin/sortable_tree.rb +4 -0
  15. data/lib/active_admin/sortable_tree/controller_actions.rb +52 -0
  16. data/lib/active_admin/sortable_tree/engine.rb +19 -0
  17. data/lib/active_admin/sortable_tree/version.rb +5 -0
  18. data/lib/active_admin/views/index_as_block_decorator.rb +30 -0
  19. data/lib/active_admin/views/index_as_sortable.rb +154 -0
  20. data/lib/activeadmin-sortable-tree.rb +1 -0
  21. data/script/rails +11 -0
  22. data/spec/dummy/README.rdoc +261 -0
  23. data/spec/dummy/Rakefile +7 -0
  24. data/spec/dummy/app/admin/category.rb +15 -0
  25. data/spec/dummy/app/admin/category_tree.rb +9 -0
  26. data/spec/dummy/app/admin/dashboard.rb +5 -0
  27. data/spec/dummy/app/assets/javascripts/active_admin.js +2 -0
  28. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  29. data/spec/dummy/app/assets/javascripts/jquery.simulate.js +314 -0
  30. data/spec/dummy/app/assets/stylesheets/active_admin.css.scss +17 -0
  31. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  32. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  33. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  34. data/spec/dummy/app/mailers/.gitkeep +0 -0
  35. data/spec/dummy/app/models/.gitkeep +0 -0
  36. data/spec/dummy/app/models/admin_user.rb +6 -0
  37. data/spec/dummy/app/models/category.rb +4 -0
  38. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  39. data/spec/dummy/config.ru +4 -0
  40. data/spec/dummy/config/application.rb +56 -0
  41. data/spec/dummy/config/boot.rb +10 -0
  42. data/spec/dummy/config/database.yml +25 -0
  43. data/spec/dummy/config/environment.rb +5 -0
  44. data/spec/dummy/config/environments/development.rb +28 -0
  45. data/spec/dummy/config/environments/production.rb +64 -0
  46. data/spec/dummy/config/environments/test.rb +32 -0
  47. data/spec/dummy/config/initializers/active_admin.rb +231 -0
  48. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  49. data/spec/dummy/config/initializers/devise.rb +256 -0
  50. data/spec/dummy/config/initializers/inflections.rb +15 -0
  51. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  52. data/spec/dummy/config/initializers/secret_token.rb +8 -0
  53. data/spec/dummy/config/initializers/session_store.rb +8 -0
  54. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  55. data/spec/dummy/config/locales/devise.en.yml +59 -0
  56. data/spec/dummy/config/locales/en.yml +5 -0
  57. data/spec/dummy/config/routes.rb +61 -0
  58. data/spec/dummy/db/migrate/20140806024135_devise_create_admin_users.rb +48 -0
  59. data/spec/dummy/db/migrate/20140806024139_create_active_admin_comments.rb +19 -0
  60. data/spec/dummy/db/migrate/20140806032156_create_categories.rb +12 -0
  61. data/spec/dummy/db/schema.rb +58 -0
  62. data/spec/dummy/lib/assets/.gitkeep +0 -0
  63. data/spec/dummy/log/.gitkeep +0 -0
  64. data/spec/dummy/public/404.html +26 -0
  65. data/spec/dummy/public/422.html +26 -0
  66. data/spec/dummy/public/500.html +25 -0
  67. data/spec/dummy/public/favicon.ico +0 -0
  68. data/spec/dummy/script/rails +6 -0
  69. data/spec/features/sortable_spec.rb +58 -0
  70. data/spec/rails_helper.rb +65 -0
  71. data/spec/spec_helper.rb +58 -0
  72. data/spec/support/wait_for_ajax.rb +19 -0
  73. data/vendor/assets/javascripts/jquery.mjs.nestedSortable.js +613 -0
  74. metadata +231 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4f09566c21b921af0c4bcb3745a383e874b62a07
4
+ data.tar.gz: a339d4935ff0540a849f5f7b59bd3b96a3922347
5
+ SHA512:
6
+ metadata.gz: 6324e646b2016b28626d43053404d991d47fb2bf73e17288971d58c0ce596655804acdfd5904e472ebf460d3fd4252467807b0cc58e46bf66bef1718face2b45
7
+ data.tar.gz: 1c361bd2c79389830cf871b14c8c10134e9cba8285ca894ee741fce1ad8c23da868ceade03f52856ca1aaa358fa97a46439409d9e371a1a6d4fb9c6837653335
@@ -0,0 +1,11 @@
1
+ .rspec
2
+ .bundle/
3
+ log/*.log
4
+ pkg/
5
+ spec/dummy/db/*.sqlite3
6
+ spec/dummy/log/*.log
7
+ spec/dummy/tmp/
8
+ spec/dummy/public/assets
9
+ spec/dummy/.sass-cache
10
+
11
+ Gemfile.lock
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ rvm:
3
+ - "1.9.3"
4
+ - "2.1.0"
5
+ env:
6
+ matrix:
7
+ - RAILS_VERSION=3.2
8
+ - RAILS_VERSION=4.0
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Declare your gem's dependencies in activeadmin-tree.gemspec.
4
+ # Bundler will treat runtime dependencies like base dependencies, and
5
+ # development dependencies will be added by default to the :development group.
6
+ gemspec
7
+
8
+ version = ENV['RAILS_VERSION'] || "4.0"
9
+
10
+ eval_gemfile File.expand_path("../gemfiles/#{version}.gemfile", __FILE__)
@@ -0,0 +1,20 @@
1
+ Copyright 2012 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,163 @@
1
+ # ActiveAdmin::SortableTree
2
+
3
+ [![Build Status](https://travis-ci.org/zorab47/active_admin-sortable_tree.svg?branch=master)](https://travis-ci.org/zorab47/active_admin-sortable_tree)
4
+
5
+ This gem adds a tree and a list view to your ActiveAdmin resource index, both
6
+ sortable via drag'n'drop.
7
+
8
+
9
+ ## Installation
10
+
11
+ ```ruby
12
+ # Gemfile
13
+ gem "active_admin-sortable_tree"
14
+ ```
15
+
16
+ *WARNING!* Not compatible with neo/activeadmin-sortable[https://github.com/neo/activeadmin-sortable]
17
+
18
+
19
+ ## Usage (Tree)
20
+
21
+ **Admin**:
22
+
23
+ ```ruby
24
+ # app/admin/page.rb
25
+ ActiveAdmin.register Page do
26
+ sortable tree: true
27
+
28
+ index :as => :sortable do
29
+ label :title # item content
30
+ actions
31
+ end
32
+ end
33
+ ```
34
+
35
+ **Model**: activeadmin-sortable-tree is agnostic to the tree implementation. All
36
+ you have to do is expose a sorting attribute and a few tree methods (:parent,
37
+ :children and :roots). Let's say you use
38
+ [Ancestry](https://github.com/stefankroes/ancestry):
39
+
40
+ ```ruby
41
+ class Page < ActiveRecord::Base
42
+ attr_accessible :title, :body, :position
43
+ has_ancestry :orphan_strategy => :rootify
44
+ end
45
+ ```
46
+
47
+ You can configure these methods if you need:
48
+
49
+ ```ruby
50
+ ActiveAdmin.register Page do
51
+ sortable tree: true,
52
+ sorting_attribute: :position,
53
+ parent_method: :parent,
54
+ children_method: :children,
55
+ roots_method: :roots,
56
+ roots_collection: proc { current_user.pages.roots }
57
+ # ...
58
+ end
59
+ ```
60
+
61
+ The option `roots_collection` provides full control on how to find the root
62
+ nodes of your sortable tree and is evaluated within the context of the
63
+ controller. Please note that `roots_collection` will override what is specified
64
+ in `roots_method`.
65
+
66
+ ## Usage (List)
67
+
68
+ **Admin**:
69
+ ```ruby
70
+ # app/admin/page.rb
71
+ ActiveAdmin.register Page do
72
+ sortable
73
+
74
+ index :as => :sortable do
75
+ label :title # item content
76
+ actions
77
+ end
78
+ end
79
+ ```
80
+
81
+ **Model**: Sortable list assumes you have a `:position` field in your resource.
82
+ Of course it's configurable:
83
+
84
+ ```ruby
85
+ ActiveAdmin.register Page do
86
+ sortable tree: false, # default
87
+ sorting_attribute: :my_position_field
88
+ ...
89
+ end
90
+ ```
91
+
92
+
93
+ ## Usage (generic ActiveAdmin index)
94
+
95
+ Currently supports only IndexAsBlock, more to come!
96
+
97
+ **Admin**:
98
+ ```ruby
99
+ # app/admin/page.rb
100
+
101
+ ActiveAdmin.register Page do
102
+ sortable
103
+
104
+ index :as => :block do |page|
105
+ # item content
106
+ end
107
+ end
108
+ ```
109
+
110
+ **Model**: Same as list view (see above)
111
+
112
+
113
+ ## Customization
114
+
115
+ ### Full options list with defaults
116
+
117
+ ```ruby
118
+ ActiveAdmin.register Page do
119
+ sortable tree: true,
120
+ max_levels: 0, # infinite indent levels
121
+ protect_root: false, # allow root items to be dragged
122
+ sorting_attribute: :position,
123
+ parent_method: :parent,
124
+ children_method: :children,
125
+ roots_method: :roots,
126
+ roots_collection: nil, # proc to specifiy retrieval of roots
127
+ collapsible: false, # show +/- buttons to collapse children
128
+ start_collapsed: false, # when collapsible, start with all roots collapsed
129
+ end
130
+ ```
131
+
132
+
133
+ ### Actions
134
+
135
+ In `IndexAsSortable` you can add custom actions (with or without the defaults):
136
+
137
+ ```ruby
138
+ index :as => :sortable do
139
+ actions defaults: false do |page|
140
+ link_to "Custom action", my_custon_path(page)
141
+ end
142
+ end
143
+ ```
144
+
145
+
146
+ ### Ajax Callback Config
147
+
148
+ It exposes three Ajax Events: ajaxDone, ajaxFail and ajaxAlways, which
149
+ correspond to jQuery ajax callbacks: done, fail and always.
150
+
151
+ To subscribe Ajax callback:
152
+
153
+ ```javascript
154
+ ActiveAdminSortableEvent.add('ajaxDone', function (){
155
+ // do what you want
156
+ })
157
+ ```
158
+
159
+ ## Copyright
160
+
161
+ Copyright © 2013 Francesco Disperati, Cantiere Creativo. See the file
162
+ MIT-LICENSE for details. See the full list list of
163
+ [contributors](https://github.com/nebirhos/activeadmin-sortable-tree/graphs/contributors).
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'ActiveAdmin::SortableTree'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+
24
+ Bundler::GemHelper.install_tasks
25
+
26
+ require 'rspec/core/rake_task'
27
+ RSpec::Core::RakeTask.new(:spec)
28
+ task default: ['dummy:prepare', :spec]
29
+
30
+ require 'rake/clean'
31
+ CLEAN.include 'spec/dummy/db/*sqlite3', 'spec/dummy/log/*', 'spec/dummy/public/assets/*', 'spec/dummy/tmp/**/*'
32
+
33
+ namespace :dummy do
34
+ desc 'Setup dummy app database'
35
+ task :prepare do
36
+ # File.expand_path is executed directory of generated Rails app
37
+ rakefile = File.expand_path('Rakefile', dummy_path)
38
+ command = "rake -f '%s' db:schema:load RAILS_ENV=test" % rakefile
39
+ sh(command) unless ENV["DISABLE_CREATE"]
40
+ end
41
+
42
+ # task :migrate do
43
+ # # File.expand_path is executed directory of generated Rails app
44
+ # rakefile = File.expand_path('Rakefile', dummy_path)
45
+ # command = "rake -f '%s' db:migrate db:test:prepare" % rakefile
46
+ # sh(command) unless ENV["DISABLE_MIGRATE"]
47
+ # end
48
+
49
+ def dummy_path
50
+ rel_path = ENV['DUMMY_APP_PATH'] || 'spec/dummy'
51
+ if @current_path.to_s.include?(rel_path)
52
+ @current_path
53
+ else
54
+ @current_path = File.expand_path(rel_path)
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,30 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+
3
+ # Maintain your gem's version:
4
+ require "active_admin/sortable_tree/version"
5
+
6
+ # Describe your gem and declare its dependencies:
7
+ Gem::Specification.new do |s|
8
+ s.name = "active_admin-sortable_tree"
9
+ s.version = ActiveAdmin::SortableTree::VERSION
10
+ s.authors = ["Francesco Disperati", 'Charles Maresh']
11
+ s.email = ["me@nebirhos.com", 'zorab47@gmail.com']
12
+ s.homepage = "https://github.com/zorab47/active_admin-sortable_tree"
13
+ s.summary = "Add drag and drop sorting to ActiveAdmin resources"
14
+ s.description = "SortableTree provides sorting of lists and hierarchies from ActiveAdmin index views."
15
+ s.license = "MIT"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_dependency 'rails', '>= 3.2'
22
+ s.add_dependency 'activeadmin', '>= 0.6'
23
+ s.add_dependency 'jquery-ui-rails', '~> 5.0'
24
+
25
+ s.add_development_dependency 'capybara'
26
+ s.add_development_dependency 'rspec-rails'
27
+ s.add_development_dependency 'phantomjs'
28
+ s.add_development_dependency 'poltergeist'
29
+ s.add_development_dependency 'database_cleaner'
30
+ end
@@ -0,0 +1,91 @@
1
+ #= require jquery-ui/sortable
2
+ #= require jquery.mjs.nestedSortable
3
+
4
+ window.ActiveAdminSortableEvent = do ->
5
+ eventToListeners = {}
6
+
7
+ return {
8
+ add: (event, callback) ->
9
+ if not eventToListeners.hasOwnProperty(event)
10
+ eventToListeners[event] = []
11
+ eventToListeners[event].push(callback)
12
+
13
+ trigger: (event, args) ->
14
+ if eventToListeners.hasOwnProperty(event)
15
+ for callback in eventToListeners[event]
16
+ try
17
+ callback.call(null, args)
18
+ catch e
19
+ console.error(e) if console and console.error
20
+ }
21
+
22
+ $ ->
23
+ $('.disclose').bind 'click', (event) ->
24
+ $(this).closest('li').toggleClass('mjs-nestedSortable-collapsed').toggleClass('mjs-nestedSortable-expanded')
25
+
26
+ $("[data-sortable-type=plain]").each ->
27
+ $this = $(@)
28
+ $this.sortable
29
+ revert: 250
30
+ update: ->
31
+ $this.sortable("disable")
32
+ $.ajax
33
+ url: $this.data("sortable-url")
34
+ type: "post"
35
+ data: $this.sortable("serialize")
36
+ .always ->
37
+ $this.sortable("enable")
38
+ ActiveAdminSortableEvent.trigger('ajaxAlways')
39
+ .done ->
40
+ ActiveAdminSortableEvent.trigger('ajaxDone')
41
+ .fail ->
42
+ ActiveAdminSortableEvent.trigger('ajaxFail')
43
+
44
+ .disableSelection()
45
+
46
+ $(".index_as_sortable [data-sortable-type]").each ->
47
+ $this = $(@)
48
+ if $this.data('sortable-type') == "tree"
49
+ max_levels = $this.data('max-levels')
50
+ tab_hack = 20 # nestedSortable default
51
+ else
52
+ max_levels = 1
53
+ tab_hack = 99999
54
+
55
+ $this.nestedSortable
56
+ forcePlaceholderSize: true
57
+ forceHelperSizeType: true
58
+ errorClass: 'cantdoit'
59
+ disableNesting: 'cantdoit'
60
+ handle: '> .item'
61
+ listType: 'ol'
62
+ items: 'li'
63
+ opacity: .6
64
+ placeholder: 'placeholder'
65
+ revert: 250
66
+ maxLevels: max_levels,
67
+ tabSize: tab_hack
68
+ protectRoot: $this.data('protect-root')
69
+ # prevent drag flickers
70
+ tolerance: 'pointer'
71
+ toleranceElement: '> div'
72
+ isTree: true
73
+ startCollapsed: $this.data("start-collapsed")
74
+ update: ->
75
+ $this.nestedSortable("disable")
76
+ $.ajax
77
+ url: $this.data("sortable-url")
78
+ type: "post"
79
+ data: $this.nestedSortable("serialize")
80
+ .always ->
81
+ $this.find('.item').each (index) ->
82
+ if index % 2
83
+ $(this).removeClass('odd').addClass('even')
84
+ else
85
+ $(this).removeClass('even').addClass('odd')
86
+ $this.nestedSortable("enable")
87
+ ActiveAdminSortableEvent.trigger('ajaxAlways')
88
+ .done ->
89
+ ActiveAdminSortableEvent.trigger('ajaxDone')
90
+ .fail ->
91
+ ActiveAdminSortableEvent.trigger('ajaxFail')
@@ -0,0 +1,79 @@
1
+ $cOddRowBackground: #f4f5f5
2
+ $cRowBorder: #e8e8e8
3
+ $cRowSelected: #d9e4ec
4
+ $cRowError: rgb(255,87,87)
5
+
6
+ @import bourbon
7
+
8
+ body.active_admin
9
+ .index_content
10
+ .ui-sortable > *
11
+ cursor: move
12
+
13
+ .disclose
14
+ cursor: pointer
15
+ width: 10px
16
+ display: none
17
+
18
+ .index_as_sortable
19
+ .resource_selection_toggle_panel
20
+ padding-left: 12px
21
+
22
+ > ol
23
+ margin: 16px 0
24
+
25
+ ol
26
+ li
27
+ cursor: default !important
28
+
29
+ &.placeholder
30
+ background: lighten($cOddRowBackground, 10%)
31
+ border: 1px dashed $cRowSelected
32
+ +box-sizing(border-box)
33
+
34
+ &.cantdoit
35
+ border: 1px dashed $cRowError
36
+
37
+ .item
38
+ width: 100%
39
+ border-top: 1px solid $cRowBorder
40
+ border-bottom: 1px solid $cRowBorder
41
+ +clearfix
42
+
43
+ &.even
44
+ background: white
45
+
46
+ &.odd
47
+ background: $cOddRowBackground
48
+
49
+ &:hover
50
+ background-color: $cRowSelected
51
+ cursor: move
52
+
53
+ .cell
54
+ margin: 0
55
+ padding: 10px 12px 8px 12px
56
+
57
+ h3.cell
58
+ font-size: 16px
59
+ line-height: 14px
60
+ color: black
61
+
62
+ > li > ol
63
+ margin-left: 30px
64
+
65
+ li.mjs-nestedSortable-collapsed > ol
66
+ display: none
67
+
68
+ li.mjs-nestedSortable-branch > div > .disclose
69
+ display: block
70
+ float: left
71
+ padding: 10px 5px 8px 5px
72
+
73
+ li.mjs-nestedSortable-collapsed > div > .disclose > span:before
74
+ content: '+ '
75
+
76
+ li.mjs-nestedSortable-expanded > div > .disclose > span:before
77
+ content: '- '
78
+
79
+