rails_admin_nestable 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.md +100 -0
- data/Rakefile +27 -0
- data/app/assets/javascripts/rails_admin/rails_admin_nestable.js.coffee +34 -0
- data/app/assets/stylesheets/rails_admin/rails_admin_nestable.css +158 -0
- data/app/helpers/rails_admin/nestable_helper.rb +5 -0
- data/app/views/rails_admin/main/nestable.html.haml +40 -0
- data/config/locales/nestable.en.yml +12 -0
- data/config/locales/nestable.it.yml +12 -0
- data/lib/rails_admin_nestable.rb +13 -0
- data/lib/rails_admin_nestable/configuration.rb +37 -0
- data/lib/rails_admin_nestable/engine.rb +4 -0
- data/lib/rails_admin_nestable/helper.rb +36 -0
- data/lib/rails_admin_nestable/model.rb +15 -0
- data/lib/rails_admin_nestable/nestable.rb +93 -0
- data/lib/rails_admin_nestable/version.rb +3 -0
- metadata +93 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2012 Andrea Dal Ponte
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
# Rails Admin Nestable
|
2
|
+
|
3
|
+
Reorganise model data with a drag and drop tree/list structure.
|
4
|
+
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
To enable rails_admin_nestable, add the following to your `Gemfile`:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
gem "rails_admin_nestable", git: "git://github.com/dalpo/rails_admin_nestable.git"
|
12
|
+
```
|
13
|
+
|
14
|
+
Add in your `config/initializers/rails_admin.rb` initializer the configuration:
|
15
|
+
```ruby
|
16
|
+
RailsAdmin.config do |config|
|
17
|
+
config.actions do
|
18
|
+
# root actions
|
19
|
+
dashboard # mandatory
|
20
|
+
# collection actions
|
21
|
+
index # mandatory
|
22
|
+
new
|
23
|
+
export
|
24
|
+
history_index
|
25
|
+
bulk_delete
|
26
|
+
# member actions
|
27
|
+
show
|
28
|
+
edit
|
29
|
+
delete
|
30
|
+
history_show
|
31
|
+
show_in_app
|
32
|
+
|
33
|
+
# Add the nestable action for each model
|
34
|
+
nestable do
|
35
|
+
visible do
|
36
|
+
[NavNode, Product].include? bindings[:abstract_model].model
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
```
|
42
|
+
|
43
|
+
## Configuration
|
44
|
+
You could choose between two different configurations for your model:
|
45
|
+
|
46
|
+
### 1. Nestable tree:
|
47
|
+
To use this configuration, you need to organize your tree model with [Ancestry](https://github.com/stefankroes/ancestry).
|
48
|
+
Otherwise your model have to respond to the `parent`, `arrange` and `children` methods.
|
49
|
+
|
50
|
+
The `nestable_tree` methods supports the following options:
|
51
|
+
* `position_field`: (symbol) default `nil`
|
52
|
+
* `max_depth`: (integer) default `nil`
|
53
|
+
|
54
|
+
In your `config/initializers/rails_admin.rb` initializer:
|
55
|
+
```ruby
|
56
|
+
RailsAdmin.config do |config|
|
57
|
+
config.actions do
|
58
|
+
...
|
59
|
+
end
|
60
|
+
|
61
|
+
config.model MyModel do
|
62
|
+
nestable_tree({ position_field: :position, max_depth: 3 })
|
63
|
+
end
|
64
|
+
end
|
65
|
+
```
|
66
|
+
|
67
|
+
|
68
|
+
### 2. Nestable list:
|
69
|
+
To use this configuration, you need a position field
|
70
|
+
|
71
|
+
The `nestable_list` methods supports the following options:
|
72
|
+
* `position_field`: (symbol) default `:position`
|
73
|
+
|
74
|
+
In your `config/initializers/rails_admin.rb` initializer:
|
75
|
+
```ruby
|
76
|
+
RailsAdmin.config do |config|
|
77
|
+
config.actions do
|
78
|
+
...
|
79
|
+
end
|
80
|
+
|
81
|
+
config.model MyModel do
|
82
|
+
nestable_list true
|
83
|
+
end
|
84
|
+
end
|
85
|
+
```
|
86
|
+
|
87
|
+
## Screenshot
|
88
|
+
|
89
|
+
![Nestable view](https://github.com/dalpo/rails_admin_nestable/raw/master/screenshots/nestable_tree.jpg "nestable view")
|
90
|
+
|
91
|
+
## Thanks
|
92
|
+
|
93
|
+
* [Carlo Scortegagna](https://github.com/carloscortegagna)
|
94
|
+
* [Andrea Zaupa](https://github.com/andreazaupa)
|
95
|
+
* [Rails Admin](https://github.com/sferik/rails_admin)
|
96
|
+
* [Nestable](http://dbushell.github.com/Nestable)
|
97
|
+
|
98
|
+
|
99
|
+
|
100
|
+
**This project rocks and uses MIT-LICENSE.**
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
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 = 'RailsAdminNestable'
|
18
|
+
rdoc.options << '--line-numbers'
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
Bundler::GemHelper.install_tasks
|
27
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
//= require jquery.nestable.js
|
2
|
+
//= require_self
|
3
|
+
|
4
|
+
$(document).ready ->
|
5
|
+
$tree_nodes = $('#tree_nodes')
|
6
|
+
$tree_nodes_options = {}
|
7
|
+
$tree_nodes_max_depth = $tree_nodes.data('max-depth')
|
8
|
+
|
9
|
+
if $tree_nodes_max_depth && $tree_nodes_max_depth != 'false'
|
10
|
+
$tree_nodes_options['maxDepth'] = $tree_nodes_max_depth
|
11
|
+
|
12
|
+
$tree_nodes
|
13
|
+
.nestable( $tree_nodes_options )
|
14
|
+
.on
|
15
|
+
change: (event) ->
|
16
|
+
serialized_tree = $tree_nodes.nestable('serialize')
|
17
|
+
|
18
|
+
$.ajax
|
19
|
+
url: $tree_nodes.data('update-path'),
|
20
|
+
type: 'POST',
|
21
|
+
data:
|
22
|
+
tree_nodes: serialized_tree
|
23
|
+
success: (data) ->
|
24
|
+
$flash = $('<div>')
|
25
|
+
.addClass('nestable-flash alert')
|
26
|
+
.append( $('<button>').addClass('close').data('dismiss', 'alert').html('×') )
|
27
|
+
.append( $('<span>').addClass('body').html( data ) )
|
28
|
+
|
29
|
+
$('#rails_admin_nestable')
|
30
|
+
.append( $flash )
|
31
|
+
|
32
|
+
$flash.fadeIn(200)
|
33
|
+
.delay(2000).fadeOut 200, ->
|
34
|
+
$(this).remove()
|
@@ -0,0 +1,158 @@
|
|
1
|
+
/**
|
2
|
+
* Nestable
|
3
|
+
*/
|
4
|
+
|
5
|
+
.dd {
|
6
|
+
position: relative;
|
7
|
+
display: block;
|
8
|
+
margin: 0;
|
9
|
+
padding: 0;
|
10
|
+
/* max-width: 600px; */
|
11
|
+
list-style: none;
|
12
|
+
font-size: 13px;
|
13
|
+
line-height: 20px; }
|
14
|
+
|
15
|
+
.dd-list {
|
16
|
+
display: block;
|
17
|
+
position: relative;
|
18
|
+
margin: 0;
|
19
|
+
padding: 0;
|
20
|
+
list-style: none;
|
21
|
+
}
|
22
|
+
.dd-list .dd-list { padding-left: 30px; }
|
23
|
+
.dd-collapsed .dd-list { display: none; }
|
24
|
+
|
25
|
+
.dd-item,
|
26
|
+
.dd-empty,
|
27
|
+
.dd-placeholder { display: block; position: relative; margin: 0; padding: 0; min-height: 20px; font-size: 13px; line-height: 20px; }
|
28
|
+
|
29
|
+
.dd-handle {
|
30
|
+
display: block; height: 30px; margin: 5px 0; padding: 5px 10px; color: #333; text-decoration: none; font-weight: bold; border: 1px solid #ccc;
|
31
|
+
background: #fafafa;
|
32
|
+
background: -webkit-linear-gradient(top, #fafafa 0%, #eee 100%);
|
33
|
+
background: -moz-linear-gradient(top, #fafafa 0%, #eee 100%);
|
34
|
+
background: linear-gradient(top, #fafafa 0%, #eee 100%);
|
35
|
+
-webkit-border-radius: 3px;
|
36
|
+
border-radius: 3px;
|
37
|
+
box-sizing: border-box; -moz-box-sizing: border-box;
|
38
|
+
}
|
39
|
+
.dd-handle:hover { color: #2ea8e5; background: #fff; }
|
40
|
+
|
41
|
+
.dd-item > button { display: block; position: relative; cursor: pointer; float: left; width: 25px; height: 20px; margin: 5px 0; padding: 0; text-indent: 100%; white-space: nowrap; overflow: hidden; border: 0; background: transparent; font-size: 12px; line-height: 1; text-align: center; font-weight: bold; }
|
42
|
+
.dd-item > button:before { content: '+'; display: block; position: absolute; width: 100%; text-align: center; text-indent: 0; }
|
43
|
+
.dd-item > button[data-action="collapse"]:before { content: '-'; }
|
44
|
+
|
45
|
+
.dd-placeholder,
|
46
|
+
.dd-empty { margin: 5px 0; padding: 0; min-height: 30px; background: #f2fbff; border: 1px dashed #b6bcbf; box-sizing: border-box; -moz-box-sizing: border-box; }
|
47
|
+
.dd-empty { border: 1px dashed #bbb; min-height: 100px; background-color: #e5e5e5;
|
48
|
+
background-image: -webkit-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff),
|
49
|
+
-webkit-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff);
|
50
|
+
background-image: -moz-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff),
|
51
|
+
-moz-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff);
|
52
|
+
background-image: linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff),
|
53
|
+
linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff);
|
54
|
+
background-size: 60px 60px;
|
55
|
+
background-position: 0 0, 30px 30px;
|
56
|
+
}
|
57
|
+
|
58
|
+
.dd-dragel { position: absolute; pointer-events: none; z-index: 9999; }
|
59
|
+
.dd-dragel > .dd-item .dd-handle { margin-top: 0; }
|
60
|
+
.dd-dragel .dd-handle {
|
61
|
+
-webkit-box-shadow: 2px 4px 6px 0 rgba(0,0,0,.1);
|
62
|
+
box-shadow: 2px 4px 6px 0 rgba(0,0,0,.1);
|
63
|
+
}
|
64
|
+
|
65
|
+
/**
|
66
|
+
* Nestable Extras
|
67
|
+
*/
|
68
|
+
|
69
|
+
.nestable-lists { display: block; clear: both; padding: 30px 0; width: 100%; border: 0; border-top: 2px solid #ddd; border-bottom: 2px solid #ddd; }
|
70
|
+
|
71
|
+
#nestable-menu { padding: 0; margin: 20px 0; }
|
72
|
+
|
73
|
+
#nestable-output,
|
74
|
+
#nestable2-output { width: 100%; height: 7em; font-size: 0.75em; line-height: 1.333333em; font-family: Consolas, monospace; padding: 5px; box-sizing: border-box; -moz-box-sizing: border-box; }
|
75
|
+
|
76
|
+
#nestable2 .dd-handle {
|
77
|
+
color: #fff;
|
78
|
+
border: 1px solid #999;
|
79
|
+
background: #bbb;
|
80
|
+
background: -webkit-linear-gradient(top, #bbb 0%, #999 100%);
|
81
|
+
background: -moz-linear-gradient(top, #bbb 0%, #999 100%);
|
82
|
+
background: linear-gradient(top, #bbb 0%, #999 100%);
|
83
|
+
}
|
84
|
+
#nestable2 .dd-handle:hover { background: #bbb; }
|
85
|
+
#nestable2 .dd-item > button:before { color: #fff; }
|
86
|
+
|
87
|
+
@media only screen and (min-width: 700px) {
|
88
|
+
|
89
|
+
.dd { float: none; width: auto; }
|
90
|
+
.dd + .dd { margin-left: 2%; }
|
91
|
+
|
92
|
+
}
|
93
|
+
|
94
|
+
.dd-hover > .dd-handle { background: #2ea8e5 !important; }
|
95
|
+
|
96
|
+
/**
|
97
|
+
* Nestable Draggable Handles
|
98
|
+
*/
|
99
|
+
|
100
|
+
.dd3-content { display: block; height: 30px; margin: 5px 0; padding: 5px 10px 5px 40px; color: #333; text-decoration: none; font-weight: bold; border: 1px solid #ccc;
|
101
|
+
background: #fafafa;
|
102
|
+
background: -webkit-linear-gradient(top, #fafafa 0%, #eee 100%);
|
103
|
+
background: -moz-linear-gradient(top, #fafafa 0%, #eee 100%);
|
104
|
+
background: linear-gradient(top, #fafafa 0%, #eee 100%);
|
105
|
+
-webkit-border-radius: 3px;
|
106
|
+
border-radius: 3px;
|
107
|
+
box-sizing: border-box; -moz-box-sizing: border-box;
|
108
|
+
}
|
109
|
+
.dd3-content:hover { color: #2ea8e5; background: #fff; }
|
110
|
+
|
111
|
+
.dd-dragel > .dd3-item > .dd3-content { margin: 0; }
|
112
|
+
|
113
|
+
.dd3-item > button { margin-left: 30px; }
|
114
|
+
|
115
|
+
.dd3-handle { position: absolute; margin: 0; left: 0; top: 0; cursor: pointer; width: 30px; text-indent: 100%; white-space: nowrap; overflow: hidden;
|
116
|
+
border: 1px solid #aaa;
|
117
|
+
background: #ddd;
|
118
|
+
background: -webkit-linear-gradient(top, #ddd 0%, #bbb 100%);
|
119
|
+
background: -moz-linear-gradient(top, #ddd 0%, #bbb 100%);
|
120
|
+
background: linear-gradient(top, #ddd 0%, #bbb 100%);
|
121
|
+
border-top-right-radius: 0;
|
122
|
+
border-bottom-right-radius: 0;
|
123
|
+
}
|
124
|
+
.dd3-handle:before { content: '≡'; display: block; position: absolute; left: 0; top: 3px; width: 100%; text-align: center; text-indent: 0; color: #fff; font-size: 20px; font-weight: normal; }
|
125
|
+
.dd3-handle:hover { background: #ddd; }
|
126
|
+
|
127
|
+
.dd3-content .links {
|
128
|
+
width: auto;
|
129
|
+
}
|
130
|
+
.dd3-content ul.inline.actions {
|
131
|
+
margin: 0;
|
132
|
+
padding: 0;
|
133
|
+
list-style: none;
|
134
|
+
display: block
|
135
|
+
}
|
136
|
+
.dd3-content ul.inline.actions li {
|
137
|
+
display: inline;
|
138
|
+
}
|
139
|
+
.dd3-content ul.inline.actions li a {
|
140
|
+
width: 14px;
|
141
|
+
height: 16px;
|
142
|
+
text-decoration: none;
|
143
|
+
}
|
144
|
+
.dd3-content ul.inline.actions li a:hover {
|
145
|
+
text-decoration: none;
|
146
|
+
}
|
147
|
+
|
148
|
+
#rails_admin_nestable {
|
149
|
+
position: relative;
|
150
|
+
}
|
151
|
+
.nestable-flash {
|
152
|
+
position: fixed;
|
153
|
+
top: 80px;
|
154
|
+
width: auto;
|
155
|
+
right: 20px;
|
156
|
+
display: none;
|
157
|
+
min-width: 150px;
|
158
|
+
}
|
@@ -0,0 +1,40 @@
|
|
1
|
+
:ruby
|
2
|
+
def nested_tree_nodes(tree_nodes = [])
|
3
|
+
tree_nodes.map do |tree_node, sub_tree_nodes|
|
4
|
+
li_classes = 'dd-item dd3-item'
|
5
|
+
|
6
|
+
content_tag :li, class: li_classes, :'data-id' => tree_node.id do
|
7
|
+
|
8
|
+
output = content_tag :div, 'drag', class: 'dd-handle dd3-handle'
|
9
|
+
output+= content_tag :div, class: 'dd3-content' do
|
10
|
+
content = link_to @model_config.with(object: tree_node).object_label, edit_path(@abstract_model, tree_node.id)
|
11
|
+
content+= content_tag :div, action_links(tree_node), class: 'pull-right links'
|
12
|
+
end
|
13
|
+
|
14
|
+
if sub_tree_nodes && sub_tree_nodes.any?
|
15
|
+
output+= content_tag :ol, nested_tree_nodes(sub_tree_nodes), class: 'dd-list'
|
16
|
+
end
|
17
|
+
|
18
|
+
output
|
19
|
+
end
|
20
|
+
end.join.html_safe
|
21
|
+
end
|
22
|
+
|
23
|
+
def action_links(model)
|
24
|
+
content_tag :ul, class: 'inline actions' do
|
25
|
+
menu_for :member, @abstract_model, model, true
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def tree_max_depth
|
30
|
+
@nestable_conf.options[:max_depth] || 'false'
|
31
|
+
end
|
32
|
+
|
33
|
+
.row-fluid
|
34
|
+
.span12#rails_admin_nestable
|
35
|
+
#tree_nodes.dd{:'data-update-path' => nestable_path(model_name: @abstract_model), :'data-max-depth' => tree_max_depth}
|
36
|
+
%ol.dd-list
|
37
|
+
= nested_tree_nodes @tree_nodes
|
38
|
+
|
39
|
+
= stylesheet_link_tag 'rails_admin/rails_admin_nestable'
|
40
|
+
= javascript_include_tag 'rails_admin/rails_admin_nestable'
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'rails_admin_nestable/engine'
|
2
|
+
|
3
|
+
module RailsAdminNestable
|
4
|
+
end
|
5
|
+
|
6
|
+
require 'rails_admin/config/actions'
|
7
|
+
require 'rails_admin/config/model'
|
8
|
+
|
9
|
+
require 'rails_admin_nestable/configuration'
|
10
|
+
require 'rails_admin_nestable/nestable'
|
11
|
+
require 'rails_admin_nestable/model'
|
12
|
+
# require 'rails_admin_nestable/helper'
|
13
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module RailsAdminNestable
|
2
|
+
class Configuration
|
3
|
+
|
4
|
+
def initialize(abstract_model)
|
5
|
+
@abstract_model = abstract_model
|
6
|
+
end
|
7
|
+
|
8
|
+
def tree?
|
9
|
+
tree.present?
|
10
|
+
end
|
11
|
+
|
12
|
+
def list?
|
13
|
+
list.present? && !tree?
|
14
|
+
end
|
15
|
+
|
16
|
+
def options
|
17
|
+
if tree?
|
18
|
+
@nestable_options ||= (tree.class == Hash ? tree : {})
|
19
|
+
elsif list?
|
20
|
+
@nestable_options ||= { position_field: :position, max_depth: 1 }.merge(list.class == Hash ? list : {})
|
21
|
+
end
|
22
|
+
|
23
|
+
@nestable_options || {}
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
def tree
|
29
|
+
@nestable_tree ||= ::RailsAdmin::Config.model(@abstract_model.model).nestable_tree
|
30
|
+
end
|
31
|
+
|
32
|
+
def list
|
33
|
+
@nestable_list ||= ::RailsAdmin::Config.model(@abstract_model.model).nestable_list
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module RailsAdminNestable
|
2
|
+
module Helper
|
3
|
+
|
4
|
+
def nested_tree_nodes(tree_nodes = [])
|
5
|
+
tree_nodes.map do |tree_node, sub_tree_nodes|
|
6
|
+
li_classes = 'dd-item dd3-item'
|
7
|
+
|
8
|
+
content_tag :li, class: li_classes, :'data-id' => tree_node.id do
|
9
|
+
|
10
|
+
output = content_tag :div, 'drag', class: 'dd-handle dd3-handle'
|
11
|
+
output+= content_tag :div, class: 'dd3-content' do
|
12
|
+
content = link_to @model_config.with(object: tree_node).object_label, edit_path(@abstract_model, tree_node.id)
|
13
|
+
content+= content_tag :div, action_links(tree_node), class: 'pull-right links'
|
14
|
+
end
|
15
|
+
|
16
|
+
if sub_tree_nodes && sub_tree_nodes.any?
|
17
|
+
output+= content_tag :ol, nested_tree_nodes(sub_tree_nodes), class: 'dd-list'
|
18
|
+
end
|
19
|
+
|
20
|
+
output
|
21
|
+
end
|
22
|
+
end.join.html_safe
|
23
|
+
end
|
24
|
+
|
25
|
+
def action_links(model)
|
26
|
+
content_tag :ul, class: 'inline actions' do
|
27
|
+
menu_for :member, @abstract_model, model, true
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def tree_max_depth
|
32
|
+
@nestable_conf.options[:max_depth] || 'false'
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module RailsAdmin
|
2
|
+
module Config
|
3
|
+
module Actions
|
4
|
+
class Nestable < Base
|
5
|
+
RailsAdmin::Config::Actions.register(self)
|
6
|
+
|
7
|
+
# Is the action acting on the root level (Example: /admin/contact)
|
8
|
+
register_instance_option :root? do
|
9
|
+
false
|
10
|
+
end
|
11
|
+
|
12
|
+
register_instance_option :collection? do
|
13
|
+
true
|
14
|
+
end
|
15
|
+
|
16
|
+
# Is the action on an object scope (Example: /admin/team/1/edit)
|
17
|
+
register_instance_option :member? do
|
18
|
+
false
|
19
|
+
end
|
20
|
+
|
21
|
+
register_instance_option :controller do
|
22
|
+
Proc.new do |klass|
|
23
|
+
@nestable_conf = ::RailsAdminNestable::Configuration.new @abstract_model
|
24
|
+
|
25
|
+
def update_tree(tree_nodes, parent_node = nil)
|
26
|
+
tree_nodes.each do |key, value|
|
27
|
+
model = @abstract_model.model.find(value['id'])
|
28
|
+
model.parent = parent_node if parent_node.present?
|
29
|
+
|
30
|
+
if @nestable_conf.options[:position_field].present?
|
31
|
+
model.send("#{@nestable_conf.options[:position_field]}=".to_sym, (key.to_i + 1))
|
32
|
+
end
|
33
|
+
|
34
|
+
model.save!(validate: false)
|
35
|
+
|
36
|
+
if value.has_key?('children')
|
37
|
+
update_tree(value['children'], model)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def update_list(model_list)
|
43
|
+
model_list.each do |key, value|
|
44
|
+
model = @abstract_model.model.find(value['id'])
|
45
|
+
model.send("#{@nestable_conf.options[:position_field]}=".to_sym, (key.to_i + 1))
|
46
|
+
model.save!(validate: false)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
if params['tree_nodes'].present?
|
51
|
+
begin
|
52
|
+
ActiveRecord::Base.transaction do
|
53
|
+
if @nestable_conf.tree?
|
54
|
+
update_tree params[:tree_nodes]
|
55
|
+
end
|
56
|
+
|
57
|
+
if @nestable_conf.list?
|
58
|
+
update_list params[:tree_nodes]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
message = "<strong>#{I18n.t('admin.actions.nestable.success')}!</strong>"
|
62
|
+
rescue Exception => e
|
63
|
+
message = "<strong>#{I18n.t('admin.actions.nestable.error')}</strong>: #{e}"
|
64
|
+
end
|
65
|
+
|
66
|
+
render text: message
|
67
|
+
else
|
68
|
+
model_scope = @abstract_model.model.unscoped
|
69
|
+
|
70
|
+
if @nestable_conf.tree?
|
71
|
+
@tree_nodes = model_scope.arrange(order: @nestable_conf.options[:position_field])
|
72
|
+
end
|
73
|
+
|
74
|
+
if @nestable_conf.list?
|
75
|
+
@tree_nodes = model_scope.order(@nestable_conf.options[:position_field])
|
76
|
+
end
|
77
|
+
|
78
|
+
render action: @action.template_name
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
register_instance_option :link_icon do
|
84
|
+
'icon-align-left'
|
85
|
+
end
|
86
|
+
|
87
|
+
register_instance_option :http_methods do
|
88
|
+
[:get, :post]
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
metadata
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rails_admin_nestable
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Andrea Dal Ponte
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-11-20 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rails
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '3.2'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '3.2'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rails_admin
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
description: Organise Ancestry model into a drag and drop tree structure
|
47
|
+
email:
|
48
|
+
- info@andreadalponte.com
|
49
|
+
executables: []
|
50
|
+
extensions: []
|
51
|
+
extra_rdoc_files: []
|
52
|
+
files:
|
53
|
+
- app/assets/javascripts/rails_admin/rails_admin_nestable.js.coffee
|
54
|
+
- app/assets/stylesheets/rails_admin/rails_admin_nestable.css
|
55
|
+
- app/helpers/rails_admin/nestable_helper.rb
|
56
|
+
- app/views/rails_admin/main/nestable.html.haml
|
57
|
+
- config/locales/nestable.en.yml
|
58
|
+
- config/locales/nestable.it.yml
|
59
|
+
- lib/rails_admin_nestable/configuration.rb
|
60
|
+
- lib/rails_admin_nestable/engine.rb
|
61
|
+
- lib/rails_admin_nestable/helper.rb
|
62
|
+
- lib/rails_admin_nestable/model.rb
|
63
|
+
- lib/rails_admin_nestable/nestable.rb
|
64
|
+
- lib/rails_admin_nestable/version.rb
|
65
|
+
- lib/rails_admin_nestable.rb
|
66
|
+
- MIT-LICENSE
|
67
|
+
- Rakefile
|
68
|
+
- README.md
|
69
|
+
homepage: https://github.com/dalpo/rails_admin_nestable
|
70
|
+
licenses: []
|
71
|
+
post_install_message:
|
72
|
+
rdoc_options: []
|
73
|
+
require_paths:
|
74
|
+
- lib
|
75
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
77
|
+
requirements:
|
78
|
+
- - ! '>='
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
none: false
|
83
|
+
requirements:
|
84
|
+
- - ! '>='
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
requirements: []
|
88
|
+
rubyforge_project:
|
89
|
+
rubygems_version: 1.8.24
|
90
|
+
signing_key:
|
91
|
+
specification_version: 3
|
92
|
+
summary: Organise Ancestry model into a drag and drop tree structure
|
93
|
+
test_files: []
|