rails_admin_nestable_sb 0.0.2
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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +159 -0
- data/Rakefile +27 -0
- data/app/assets/javascripts/rails_admin/jquery.nestable.js +508 -0
- data/app/assets/javascripts/rails_admin/nestable.js +39 -0
- data/app/assets/javascripts/rails_admin/rails_admin_nestable.js.coffee +46 -0
- data/app/assets/stylesheets/rails_admin/rails_admin_nestable.css.scss +165 -0
- data/app/helpers/rails_admin/nestable_helper.rb +4 -0
- data/app/views/rails_admin/main/nestable.html.haml +22 -0
- data/config/locales/nestable.de.yml +14 -0
- data/config/locales/nestable.en.yml +14 -0
- data/config/locales/nestable.es.yml +15 -0
- data/config/locales/nestable.fr.yml +14 -0
- data/config/locales/nestable.it.yml +14 -0
- data/config/locales/nestable.nl.yml +14 -0
- data/config/locales/nestable.ru.yml +14 -0
- data/config/locales/nestable.sv.yml +14 -0
- data/config/locales/nestable.vi.yml +14 -0
- data/lib/rails_admin_nestable/configuration.rb +46 -0
- data/lib/rails_admin_nestable/engine.rb +13 -0
- data/lib/rails_admin_nestable/helper.rb +66 -0
- data/lib/rails_admin_nestable/model.rb +15 -0
- data/lib/rails_admin_nestable/nestable.rb +110 -0
- data/lib/rails_admin_nestable/version.rb +3 -0
- data/lib/rails_admin_nestable_sb.rb +12 -0
- metadata +128 -0
@@ -0,0 +1,165 @@
|
|
1
|
+
/**
|
2
|
+
* jQuery 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
|
+
|
16
|
+
.dd-list {
|
17
|
+
display: block;
|
18
|
+
position: relative;
|
19
|
+
margin: 0;
|
20
|
+
padding: 0;
|
21
|
+
list-style: none;
|
22
|
+
}
|
23
|
+
.dd-list .dd-list { padding-left: 30px; }
|
24
|
+
.dd-collapsed .dd-list { display: none; }
|
25
|
+
|
26
|
+
.dd-item,
|
27
|
+
.dd-empty,
|
28
|
+
.dd-placeholder { display: block; position: relative; margin: 0; padding: 0; min-height: 20px; font-size: 13px; line-height: 20px; }
|
29
|
+
|
30
|
+
.dd-handle {
|
31
|
+
display: block; height: 30px; margin: 5px 0; padding: 5px 10px; color: #333; text-decoration: none; font-weight: bold; border: 1px solid #ccc;
|
32
|
+
background: #fafafa;
|
33
|
+
background: -webkit-linear-gradient(top, #fafafa 0%, #eee 100%);
|
34
|
+
background: -moz-linear-gradient(top, #fafafa 0%, #eee 100%);
|
35
|
+
background: linear-gradient(top, #fafafa 0%, #eee 100%);
|
36
|
+
-webkit-border-radius: 3px;
|
37
|
+
border-radius: 3px;
|
38
|
+
box-sizing: border-box; -moz-box-sizing: border-box;
|
39
|
+
}
|
40
|
+
.dd-handle:hover { color: #2ea8e5; background: #fff; }
|
41
|
+
|
42
|
+
.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; }
|
43
|
+
.dd-item > button:before { content: '+'; display: block; position: absolute; width: 100%; text-align: center; text-indent: 0; }
|
44
|
+
.dd-item > button[data-action="collapse"]:before { content: '-'; }
|
45
|
+
|
46
|
+
.dd-placeholder,
|
47
|
+
.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; }
|
48
|
+
.dd-empty { border: 1px dashed #bbb; min-height: 100px; background-color: #e5e5e5;
|
49
|
+
background-image: -webkit-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff),
|
50
|
+
-webkit-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff);
|
51
|
+
background-image: -moz-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff),
|
52
|
+
-moz-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff);
|
53
|
+
background-image: linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff),
|
54
|
+
linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff);
|
55
|
+
background-size: 60px 60px;
|
56
|
+
background-position: 0 0, 30px 30px;
|
57
|
+
}
|
58
|
+
|
59
|
+
.dd-dragel { position: absolute; pointer-events: none; z-index: 9999; }
|
60
|
+
.dd-dragel > .dd-item .dd-handle { margin-top: 0; }
|
61
|
+
.dd-dragel .dd-handle {
|
62
|
+
-webkit-box-shadow: 2px 4px 6px 0 rgba(0,0,0,.1);
|
63
|
+
box-shadow: 2px 4px 6px 0 rgba(0,0,0,.1);
|
64
|
+
}
|
65
|
+
|
66
|
+
/**
|
67
|
+
* Nestable Extras
|
68
|
+
*/
|
69
|
+
|
70
|
+
.nestable-lists { display: block; clear: both; padding: 30px 0; width: 100%; border: 0; border-top: 2px solid #ddd; border-bottom: 2px solid #ddd; }
|
71
|
+
|
72
|
+
#nestable-menu { padding: 0; margin: 20px 0; }
|
73
|
+
|
74
|
+
#nestable-output,
|
75
|
+
#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; }
|
76
|
+
|
77
|
+
#nestable2 .dd-handle {
|
78
|
+
color: #fff;
|
79
|
+
border: 1px solid #999;
|
80
|
+
background: #bbb;
|
81
|
+
background: -webkit-linear-gradient(top, #bbb 0%, #999 100%);
|
82
|
+
background: -moz-linear-gradient(top, #bbb 0%, #999 100%);
|
83
|
+
background: linear-gradient(top, #bbb 0%, #999 100%);
|
84
|
+
}
|
85
|
+
#nestable2 .dd-handle:hover { background: #bbb; }
|
86
|
+
#nestable2 .dd-item > button:before { color: #fff; }
|
87
|
+
|
88
|
+
@media only screen and (min-width: 700px) {
|
89
|
+
|
90
|
+
.dd { float: none; width: auto; }
|
91
|
+
.dd + .dd { margin-left: 2%; }
|
92
|
+
|
93
|
+
}
|
94
|
+
|
95
|
+
.dd-hover > .dd-handle { background: #2ea8e5 !important; }
|
96
|
+
|
97
|
+
/**
|
98
|
+
* Nestable Draggable Handles
|
99
|
+
*/
|
100
|
+
|
101
|
+
.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;
|
102
|
+
background: #fafafa;
|
103
|
+
background: -webkit-linear-gradient(top, #fafafa 0%, #eee 100%);
|
104
|
+
background: -moz-linear-gradient(top, #fafafa 0%, #eee 100%);
|
105
|
+
background: linear-gradient(top, #fafafa 0%, #eee 100%);
|
106
|
+
-webkit-border-radius: 3px;
|
107
|
+
border-radius: 3px;
|
108
|
+
box-sizing: border-box; -moz-box-sizing: border-box;
|
109
|
+
}
|
110
|
+
.dd3-content:hover { color: #2ea8e5; background: #fff; }
|
111
|
+
|
112
|
+
.dd-dragel > .dd3-item > .dd3-content { margin: 0; }
|
113
|
+
|
114
|
+
.dd3-item > button { margin-left: 30px; }
|
115
|
+
|
116
|
+
.dd3-handle {
|
117
|
+
position: absolute;
|
118
|
+
margin: 0;
|
119
|
+
left: 0;
|
120
|
+
top: 0;
|
121
|
+
cursor: pointer;
|
122
|
+
width: 30px;
|
123
|
+
text-indent: 100px;
|
124
|
+
white-space: nowrap;
|
125
|
+
overflow: hidden;
|
126
|
+
border: 1px solid #aaa;
|
127
|
+
background: #ddd;
|
128
|
+
background: -webkit-linear-gradient(top, #ddd 0%, #bbb 100%);
|
129
|
+
background: -moz-linear-gradient(top, #ddd 0%, #bbb 100%);
|
130
|
+
background: linear-gradient(top, #ddd 0%, #bbb 100%);
|
131
|
+
border-top-right-radius: 0;
|
132
|
+
border-bottom-right-radius: 0;
|
133
|
+
}
|
134
|
+
.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; }
|
135
|
+
.dd3-handle:hover { background: #ddd; }
|
136
|
+
|
137
|
+
.dd3-content .links {
|
138
|
+
width: auto;
|
139
|
+
}
|
140
|
+
.dd3-content ul.inline.actions {
|
141
|
+
margin: 0;
|
142
|
+
padding: 0;
|
143
|
+
list-style: none;
|
144
|
+
display: block
|
145
|
+
}
|
146
|
+
.dd3-content ul.inline.actions li a {
|
147
|
+
width: 14px;
|
148
|
+
height: 16px;
|
149
|
+
text-decoration: none;
|
150
|
+
}
|
151
|
+
.dd3-content ul.inline.actions li a:hover {
|
152
|
+
text-decoration: none;
|
153
|
+
}
|
154
|
+
|
155
|
+
#rails_admin_nestable {
|
156
|
+
position: relative;
|
157
|
+
}
|
158
|
+
.nestable-flash {
|
159
|
+
position: fixed;
|
160
|
+
top: 80px;
|
161
|
+
width: auto;
|
162
|
+
right: 20px;
|
163
|
+
display: none;
|
164
|
+
min-width: 150px;
|
165
|
+
}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
- #byebug
|
2
|
+
#rails_admin_nestable
|
3
|
+
= form_tag(nestable_path(model_name: @abstract_model), method: :get, class: "pjax-form form-inline") do
|
4
|
+
.well
|
5
|
+
.input-group
|
6
|
+
%input.form-control.input-small{name: "query", type: "search", value: params[:query], placeholder: t("admin.misc.filter")}
|
7
|
+
%span.input-group-btn
|
8
|
+
%button.btn.btn-primary{type: 'submit', :'data-disable-with' => '<i class="icon-white icon-refresh"></i> '.html_safe + t('admin.misc.refresh')}
|
9
|
+
%i.icon-white.icon-refresh
|
10
|
+
= t('admin.misc.refresh')
|
11
|
+
%button#remove_filter.btn.btn-info{title: "Reset filters"}
|
12
|
+
%i.icon-white.icon-remove
|
13
|
+
.form-group
|
14
|
+
#tree_nodes.dd{ data: { update_path: nestable_path(model_name: @abstract_model), max_depth: tree_max_depth } }
|
15
|
+
%ol.dd-list
|
16
|
+
= nested_family @tree_nodes
|
17
|
+
%button#save.btn.btn-primary{ style: 'float: left', type: 'submit' }= t('admin.actions.nestable.update')
|
18
|
+
#result{ style: 'float: left; margin: 7px'}
|
19
|
+
|
20
|
+
= stylesheet_link_tag 'rails_admin/rails_admin_nestable'
|
21
|
+
= javascript_include_tag 'rails_admin/jquery.nestable'
|
22
|
+
= javascript_include_tag 'rails_admin/nestable'
|
@@ -0,0 +1,14 @@
|
|
1
|
+
de:
|
2
|
+
admin:
|
3
|
+
actions:
|
4
|
+
nestable:
|
5
|
+
title: "%{model_label} sortieren"
|
6
|
+
menu: "Sortieren"
|
7
|
+
breadcrumb: "Sortieren"
|
8
|
+
link: "Sortieren"
|
9
|
+
bulk_link: "%{model_label_plural} sortieren"
|
10
|
+
done: "Sortiert"
|
11
|
+
success: "Sortierung gespeichert"
|
12
|
+
error: "Fehler"
|
13
|
+
update: "Speichern"
|
14
|
+
live_update: "Automatisch speichern"
|
@@ -0,0 +1,14 @@
|
|
1
|
+
en:
|
2
|
+
admin:
|
3
|
+
actions:
|
4
|
+
nestable:
|
5
|
+
title: "Sorting for %{model_label}"
|
6
|
+
menu: "Sorting"
|
7
|
+
breadcrumb: "Sorting"
|
8
|
+
link: "Sorting"
|
9
|
+
bulk_link: "Sort selected %{model_label_plural}"
|
10
|
+
done: "Sorted"
|
11
|
+
success: "Success"
|
12
|
+
error: "Error"
|
13
|
+
update: "Update"
|
14
|
+
live_update: "Live update"
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
es:
|
3
|
+
admin:
|
4
|
+
actions:
|
5
|
+
nestable:
|
6
|
+
title: "Ordenación para %{model_label}"
|
7
|
+
menu: "Ordenación"
|
8
|
+
breadcrumb: "Ordenación"
|
9
|
+
link: "Ordenación"
|
10
|
+
bulk_link: "Seleccionar ordenados %{model_label_plural}"
|
11
|
+
done: "Ordenado"
|
12
|
+
success: "Actualizado con éxito"
|
13
|
+
error: "Error"
|
14
|
+
update: "Actualizar"
|
15
|
+
live_update: "Actualizar en vivo"
|
@@ -0,0 +1,14 @@
|
|
1
|
+
fr:
|
2
|
+
admin:
|
3
|
+
actions:
|
4
|
+
nestable:
|
5
|
+
title: "Trier les %{model_label_plural}"
|
6
|
+
menu: "Trier"
|
7
|
+
breadcrumb: "Triage"
|
8
|
+
link: "Triage"
|
9
|
+
bulk_link: "Trier la selection de %{model_label_plural}"
|
10
|
+
done: "Trié"
|
11
|
+
success: "Succès"
|
12
|
+
error: "Erreur"
|
13
|
+
update: "Mettre à jour"
|
14
|
+
live_update: "Mise à jour auto."
|
@@ -0,0 +1,14 @@
|
|
1
|
+
it:
|
2
|
+
admin:
|
3
|
+
actions:
|
4
|
+
nestable:
|
5
|
+
title: "Ordinamento %{model_label}"
|
6
|
+
menu: "Ordinamento"
|
7
|
+
breadcrumb: "Ordinamento"
|
8
|
+
link: "Ordinamento"
|
9
|
+
bulk_link: "Ordinamento %{model_label_plural}"
|
10
|
+
done: "Salvato"
|
11
|
+
success: "Salvato"
|
12
|
+
error: "Errore"
|
13
|
+
update: "Aggiorna"
|
14
|
+
live_update: "Aggiornamento automatico"
|
@@ -0,0 +1,14 @@
|
|
1
|
+
nl:
|
2
|
+
admin:
|
3
|
+
actions:
|
4
|
+
nestable:
|
5
|
+
title: "%{model_label} sorteren"
|
6
|
+
menu: "Sorteren"
|
7
|
+
breadcrumb: "Sorteren"
|
8
|
+
link: "Sorteren"
|
9
|
+
bulk_link: "%{model_label_plural} sorteren"
|
10
|
+
done: "Gesorteerd"
|
11
|
+
success: "Succes"
|
12
|
+
error: "Error"
|
13
|
+
update: "Opslaan"
|
14
|
+
live_update: "Automatisch opslaan"
|
@@ -0,0 +1,14 @@
|
|
1
|
+
ru:
|
2
|
+
admin:
|
3
|
+
actions:
|
4
|
+
nestable:
|
5
|
+
title: "Сортировка по %{model_label}"
|
6
|
+
menu: "Сортировка"
|
7
|
+
breadcrumb: "Сортировка"
|
8
|
+
link: "Сортировка"
|
9
|
+
bulk_link: "Сортировать выбранные %{model_label_plural}"
|
10
|
+
done: "Отсортирован"
|
11
|
+
success: "Успешно"
|
12
|
+
error: "Ошибка"
|
13
|
+
update: "Обновление"
|
14
|
+
live_update: "Живое обновление"
|
@@ -0,0 +1,14 @@
|
|
1
|
+
sv:
|
2
|
+
admin:
|
3
|
+
actions:
|
4
|
+
nestable:
|
5
|
+
title: "Sortering för %{model_label}"
|
6
|
+
menu: "Sortering"
|
7
|
+
breadcrumb: "Sortering"
|
8
|
+
link: "Sortering"
|
9
|
+
bulk_link: "Vald sortering %{model_label_plural}"
|
10
|
+
done: "Sorterad"
|
11
|
+
success: "Sparad"
|
12
|
+
error: "Fel"
|
13
|
+
update: "Uppdatera"
|
14
|
+
live_update: "Uppdatera i realtid"
|
@@ -0,0 +1,14 @@
|
|
1
|
+
vi:
|
2
|
+
admin:
|
3
|
+
actions:
|
4
|
+
nestable:
|
5
|
+
title: "Sắp xếp cho %{model_label}"
|
6
|
+
menu: "Tạo Menu"
|
7
|
+
breadcrumb: "Tạo menu"
|
8
|
+
link: "Tạo menu"
|
9
|
+
bulk_link: "Sắp xếp những %{model_label_plural} đã chọn"
|
10
|
+
done: "Đã sắp xếp"
|
11
|
+
success: "Thành công"
|
12
|
+
error: "Lỗi"
|
13
|
+
update: "Cập nhập"
|
14
|
+
live_update: "Cập nhật trực tiếp"
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module RailsAdminNestable
|
2
|
+
class Configuration
|
3
|
+
|
4
|
+
TREE_DEFAULT_OPTIONS = { live_update: true, enable_callback: false, scope: nil }
|
5
|
+
LIST_DEFAULT_OPTIONS = { position_field: :position, max_depth: 1, live_update: true, enable_callback: false, scope: nil }
|
6
|
+
|
7
|
+
def initialize(abstract_model)
|
8
|
+
@abstract_model = abstract_model
|
9
|
+
end
|
10
|
+
|
11
|
+
def tree?
|
12
|
+
tree.present?
|
13
|
+
end
|
14
|
+
|
15
|
+
def list?
|
16
|
+
list.present? && !tree?
|
17
|
+
end
|
18
|
+
|
19
|
+
def options
|
20
|
+
@nestable_options ||= begin
|
21
|
+
options = self.tree_options if tree?
|
22
|
+
options = self.list_options if list?
|
23
|
+
options || {}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
|
29
|
+
def tree_options
|
30
|
+
tree.class == Hash ? TREE_DEFAULT_OPTIONS.merge(tree) : TREE_DEFAULT_OPTIONS
|
31
|
+
end
|
32
|
+
|
33
|
+
def list_options
|
34
|
+
LIST_DEFAULT_OPTIONS.merge(list.class == Hash ? list : {})
|
35
|
+
end
|
36
|
+
|
37
|
+
def tree
|
38
|
+
@nestable_tree ||= ::RailsAdmin::Config.model(@abstract_model.model).nestable_tree
|
39
|
+
end
|
40
|
+
|
41
|
+
def list
|
42
|
+
@nestable_list ||= ::RailsAdmin::Config.model(@abstract_model.model).nestable_list
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module RailsAdminNestable
|
2
|
+
class Engine < ::Rails::Engine
|
3
|
+
|
4
|
+
initializer "RailsAdminNestable precompile hook", group: :all do |app|
|
5
|
+
app.config.assets.precompile += %w(rails_admin/rails_admin_nestable.js rails_admin/jquery.nestable.js rails_admin/rails_admin_nestable.css rails_admin/nestable.js)
|
6
|
+
end
|
7
|
+
|
8
|
+
initializer 'Include RailsAdminNestable::Helper' do |app|
|
9
|
+
ActionView::Base.send :include, RailsAdminNestable::Helper
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'rails_admin/abstract_model'
|
2
|
+
|
3
|
+
module RailsAdminNestable
|
4
|
+
module Helper
|
5
|
+
def nested_tree_nodes(tree_nodes = [])
|
6
|
+
tree_nodes.map do |tree_node, sub_tree_nodes|
|
7
|
+
li_classes = 'dd-item dd3-item'
|
8
|
+
content_tag :li, class: li_classes, :'data-id' => tree_node.id do
|
9
|
+
output = content_tag :div, 'drag', class: 'dd-handle dd3-handle'
|
10
|
+
output += content_tag :div, class: 'dd3-content' do
|
11
|
+
content = link_to @model_config.with(object: tree_node).object_label, edit_path(@abstract_model, tree_node.id)
|
12
|
+
content += content_tag :div, action_links(tree_node), class: 'pull-right links'
|
13
|
+
end
|
14
|
+
|
15
|
+
output+= content_tag :ol, nested_tree_nodes(sub_tree_nodes), class: 'dd-list' if sub_tree_nodes && sub_tree_nodes.any?
|
16
|
+
output
|
17
|
+
end
|
18
|
+
end.join.html_safe
|
19
|
+
end
|
20
|
+
|
21
|
+
def nested_family(tree_nodes = [])
|
22
|
+
return if tree_nodes.nil?
|
23
|
+
tree_nodes.map do |tree_node, sub_tree_nodes|
|
24
|
+
li_classes = 'dd-item dd3-item'
|
25
|
+
|
26
|
+
content_tag :li, class: li_classes, data: { id: tree_node.id, 'dragable': 'false' } do
|
27
|
+
output = content_tag :div, 'drag', class: 'dd-handle dd3-handle'
|
28
|
+
output += content_tag :div, class: 'dd3-content' do
|
29
|
+
content = link_to @model_config.with(object: tree_node).object_label, edit_path(@abstract_model, tree_node.id)
|
30
|
+
content += content_tag :div, action_links(@abstract_model, tree_node), class: 'pull-right links'
|
31
|
+
end
|
32
|
+
|
33
|
+
child_output = ""
|
34
|
+
card_children = @child_model.where(@foreign_key => tree_node.id.to_s)
|
35
|
+
card_children.each do |card|
|
36
|
+
child_output += content_tag :li, class: 'dd-item dd3-item', data: { id: card.id, 'group': card.id } do
|
37
|
+
levelone = content_tag :div, 'drag', class: 'dd-handle dd3-handle'
|
38
|
+
levelone += content_tag :div, class: 'dd3-content' do
|
39
|
+
card_abstract = RailsAdmin::AbstractModel.new(to_model_name(@child_model.name))
|
40
|
+
content = link_to card.punchline, edit_path(card_abstract, card.id)
|
41
|
+
content += content_tag :div, action_links(card_abstract, card), class: 'pull-right links'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
output+= content_tag :ol, child_output.html_safe, class: 'dd-list' if !child_output.empty?
|
47
|
+
output
|
48
|
+
end
|
49
|
+
end.join.html_safe
|
50
|
+
end
|
51
|
+
|
52
|
+
def action_links(abstract, model)
|
53
|
+
content_tag :ul, class: 'inline list-inline' do
|
54
|
+
menu_for :member, abstract, model, true
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def to_model_name(param)
|
59
|
+
param.split('~').collect(&:camelize).join('::')
|
60
|
+
end
|
61
|
+
|
62
|
+
def tree_max_depth
|
63
|
+
@nestable_conf.options[:max_depth] || 'false'
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
module RailsAdmin
|
2
|
+
module Config
|
3
|
+
module Actions
|
4
|
+
class Nestable < Base
|
5
|
+
RailsAdmin::Config::Actions.register(self)
|
6
|
+
|
7
|
+
register_instance_option :pjax? do
|
8
|
+
true
|
9
|
+
end
|
10
|
+
|
11
|
+
register_instance_option :root? do
|
12
|
+
false
|
13
|
+
end
|
14
|
+
|
15
|
+
register_instance_option :collection? do
|
16
|
+
true
|
17
|
+
end
|
18
|
+
|
19
|
+
register_instance_option :member? do
|
20
|
+
false
|
21
|
+
end
|
22
|
+
|
23
|
+
register_instance_option :controller do
|
24
|
+
Proc.new do |klass|
|
25
|
+
@nestable_conf = ::RailsAdminNestable::Configuration.new @abstract_model
|
26
|
+
@position_field = @nestable_conf.options[:position_field]
|
27
|
+
@enable_callback = @nestable_conf.options[:enable_callback]
|
28
|
+
@nestable_scope = @nestable_conf.options[:scope]
|
29
|
+
@options = @nestable_conf.options
|
30
|
+
@adapter = @abstract_model.adapter
|
31
|
+
@child_model = @nestable_conf.options[:child_model]
|
32
|
+
@foreign_key = @nestable_conf.options[:foreign_key]
|
33
|
+
|
34
|
+
# Methods
|
35
|
+
def update_tree(tree_nodes)
|
36
|
+
tree_nodes.each do |key, value|
|
37
|
+
if value.has_key?('children')
|
38
|
+
value[:children].each do |k, v|
|
39
|
+
model = @child_model.where(@foreign_key => value['id'].to_s, id: v['id']).first
|
40
|
+
model.send("#{@position_field}=".to_sym, (k.to_i + 1)) if @position_field.present?
|
41
|
+
model.save!(validate: @enable_callback)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def update_list(model_list)
|
48
|
+
model_list.each do |key, value|
|
49
|
+
model = @abstract_model.model.find(value['id'].to_s)
|
50
|
+
model.send("#{@position_field}=".to_sym, (key.to_i + 1))
|
51
|
+
model.save!(validate: @enable_callback)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
if request.post? && params['tree_nodes'].present?
|
56
|
+
begin
|
57
|
+
update = ->{
|
58
|
+
update_tree params[:tree_nodes] if @nestable_conf.tree?
|
59
|
+
update_list params[:tree_nodes] if @nestable_conf.list?
|
60
|
+
}
|
61
|
+
|
62
|
+
ActiveRecord::Base.transaction { update.call } if @adapter == :active_record
|
63
|
+
update.call if @adapter == :mongoid
|
64
|
+
|
65
|
+
message = "<strong>#{I18n.t('admin.actions.nestable.success')}!</strong>"
|
66
|
+
rescue Exception => e
|
67
|
+
message = "<strong>#{I18n.t('admin.actions.nestable.error')}</strong>: #{e}"
|
68
|
+
end
|
69
|
+
|
70
|
+
render plain: message
|
71
|
+
end
|
72
|
+
|
73
|
+
if request.get?
|
74
|
+
#byebug
|
75
|
+
|
76
|
+
search_string = params[:search].downcase unless params[:search].nil?
|
77
|
+
|
78
|
+
query = list_entries(@model_config, :nestable, false, false)
|
79
|
+
.where("LOWER(name) LIKE ?", "%#{search_string}%")
|
80
|
+
.reorder(nil)
|
81
|
+
|
82
|
+
case @options[:scope].class.to_s
|
83
|
+
when 'Proc'
|
84
|
+
query.merge!(@options[:scope].call)
|
85
|
+
when 'Symbol'
|
86
|
+
query.merge!(@abstract_model.model.public_send(@options[:scope]))
|
87
|
+
end
|
88
|
+
|
89
|
+
@tree_nodes = query
|
90
|
+
render action: @action.template_name
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
register_instance_option :link_icon do
|
96
|
+
'icon-move fa fa-arrows'
|
97
|
+
end
|
98
|
+
|
99
|
+
register_instance_option :http_methods do
|
100
|
+
[:get, :post]
|
101
|
+
end
|
102
|
+
|
103
|
+
register_instance_option :visible? do
|
104
|
+
current_model = ::RailsAdmin::Config.model(bindings[:abstract_model])
|
105
|
+
authorized? && (current_model.nestable_tree || current_model.nestable_list)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,12 @@
|
|
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'
|