effective_datatables 3.6.3 → 3.7.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.
- checksums.yaml +4 -4
- data/MIT-LICENSE +1 -1
- data/app/assets/javascripts/dataTables/locales/en.lang +33 -0
- data/app/assets/javascripts/dataTables/locales/es.lang +36 -0
- data/app/assets/javascripts/dataTables/locales/nl.lang +30 -0
- data/app/assets/javascripts/effective_datatables/filters.js.coffee +1 -0
- data/app/assets/javascripts/effective_datatables/flash.js.coffee +31 -0
- data/app/assets/javascripts/effective_datatables/initialize.js.coffee +41 -53
- data/app/assets/javascripts/effective_datatables/inline_crud.js.coffee +217 -0
- data/app/assets/javascripts/effective_datatables/overrides.js.coffee +7 -0
- data/app/assets/javascripts/effective_datatables/reorder.js.coffee +43 -0
- data/app/assets/javascripts/effective_datatables/reset.js.coffee +1 -1
- data/app/assets/stylesheets/effective_datatables/_overrides.scss +28 -0
- data/app/controllers/effective/datatables_controller.rb +39 -6
- data/app/datatables/effective_style_guide_datatable.rb +47 -0
- data/app/helpers/effective_datatables_helper.rb +49 -56
- data/app/helpers/effective_datatables_private_helper.rb +137 -11
- data/app/models/effective/datatable.rb +36 -16
- data/app/models/effective/datatable_column.rb +1 -0
- data/app/models/effective/datatable_value_tool.rb +20 -20
- data/app/models/effective/effective_datatable/attributes.rb +5 -13
- data/app/models/effective/effective_datatable/collection.rb +18 -3
- data/app/models/effective/effective_datatable/compute.rb +15 -6
- data/app/models/effective/effective_datatable/cookie.rb +19 -18
- data/app/models/effective/effective_datatable/dsl.rb +8 -3
- data/app/models/effective/effective_datatable/dsl/bulk_actions.rb +16 -23
- data/app/models/effective/effective_datatable/dsl/datatable.rb +70 -28
- data/app/models/effective/effective_datatable/dsl/filters.rb +12 -4
- data/app/models/effective/effective_datatable/format.rb +1 -4
- data/app/models/effective/effective_datatable/params.rb +9 -4
- data/app/models/effective/effective_datatable/resource.rb +129 -74
- data/app/models/effective/effective_datatable/state.rb +30 -15
- data/app/views/effective/datatables/_bulk_actions_dropdown.html.haml +3 -5
- data/app/views/effective/datatables/_datatable.html.haml +3 -5
- data/app/views/effective/datatables/_filters.html.haml +4 -24
- data/app/views/effective/datatables/_reorder_column.html.haml +5 -0
- data/app/views/effective/style_guide/_effective_datatables.html.haml +1 -0
- data/config/effective_datatables.rb +8 -21
- data/config/locales/en.yml +12 -0
- data/config/locales/es.yml +12 -0
- data/config/locales/nl.yml +12 -0
- data/config/routes.rb +5 -4
- data/lib/effective_datatables.rb +49 -2
- data/lib/effective_datatables/engine.rb +4 -2
- data/lib/effective_datatables/version.rb +1 -1
- metadata +17 -5
- data/app/views/effective/datatables/_reset.html.haml +0 -2
@@ -0,0 +1,43 @@
|
|
1
|
+
reorder = (event, diff, edit) ->
|
2
|
+
change = diff.find (obj) -> obj.node == edit.triggerRow.node()
|
3
|
+
return unless change?
|
4
|
+
|
5
|
+
$table = $(event.currentTarget)
|
6
|
+
oldNode = $("<div>#{change.oldData}</div>").find('input[data-reorder-resource]')
|
7
|
+
newNode = $("<div>#{change.newData}</div>").find('input[data-reorder-resource]')
|
8
|
+
return unless oldNode? && newNode?
|
9
|
+
|
10
|
+
url = @context[0].ajax.url.replace('.json', '/reorder.json')
|
11
|
+
data = {'reorder[id]': oldNode.data('reorder-resource'), 'reorder[old]': oldNode.val(), 'reorder[new]': newNode.val(), attributes: $table.data('attributes') }
|
12
|
+
|
13
|
+
@context[0].rowreorder.c.enable = false
|
14
|
+
|
15
|
+
$.ajax(
|
16
|
+
method: 'post',
|
17
|
+
url: url,
|
18
|
+
data: data,
|
19
|
+
async: false
|
20
|
+
).fail((response, text, status) =>
|
21
|
+
$(event.target).closest('table').DataTable().flash(status, 'danger')
|
22
|
+
).always((response) =>
|
23
|
+
@context[0].rowreorder.c.enable = true
|
24
|
+
)
|
25
|
+
|
26
|
+
$.fn.DataTable.Api.register('reorder()', reorder);
|
27
|
+
|
28
|
+
$(document).on 'click', '.dataTables_wrapper a.buttons-reorder', (event) ->
|
29
|
+
event.preventDefault() # prevent the click
|
30
|
+
|
31
|
+
$link = $(event.currentTarget)
|
32
|
+
$table = $link.closest('.dataTables_wrapper').find('table.dataTable').first()
|
33
|
+
|
34
|
+
column = $table.DataTable().column('.col-_reorder')
|
35
|
+
return unless column.length > 0
|
36
|
+
|
37
|
+
if column.visible()
|
38
|
+
$table.removeClass('reordering')
|
39
|
+
else
|
40
|
+
$table.addClass('reordering')
|
41
|
+
|
42
|
+
column.visible(!column.visible())
|
43
|
+
|
@@ -1,4 +1,4 @@
|
|
1
|
-
$(document).on 'click', 'a.buttons-reset-search', (event) ->
|
1
|
+
$(document).on 'click', '.dataTables_wrapper a.buttons-reset-search', (event) ->
|
2
2
|
event.preventDefault() # prevent the click
|
3
3
|
|
4
4
|
$table = $(event.currentTarget).closest('.dataTables_wrapper').find('table.dataTable').first()
|
@@ -35,6 +35,8 @@ table.dataTable thead {
|
|
35
35
|
border-bottom: none;
|
36
36
|
white-space: nowrap;
|
37
37
|
padding: 6px;
|
38
|
+
|
39
|
+
span { display: block; }
|
38
40
|
}
|
39
41
|
|
40
42
|
.form-control, .form-group {
|
@@ -194,3 +196,29 @@ table.dataTable {
|
|
194
196
|
p { margin-bottom: 0px; }
|
195
197
|
}
|
196
198
|
}
|
199
|
+
|
200
|
+
// Simple styles
|
201
|
+
table.dataTable.hide-sort > thead {
|
202
|
+
.sorting { background-image: none; cursor: default; }
|
203
|
+
.sorting_asc { background-image: none; cursor: default; }
|
204
|
+
.sorting_desc { background-image: none; cursor: default; }
|
205
|
+
}
|
206
|
+
|
207
|
+
table.dataTable.hide-search > thead {
|
208
|
+
.form-group { display: none; }
|
209
|
+
}
|
210
|
+
|
211
|
+
table.dataTable.hide-buttons {
|
212
|
+
.col-bulk_actions { display: none; }
|
213
|
+
}
|
214
|
+
|
215
|
+
// Datatables entries
|
216
|
+
@media screen and (max-width: 767px) {
|
217
|
+
div.dataTables_wrapper div.dataTables_entries { text-align: center; }
|
218
|
+
}
|
219
|
+
|
220
|
+
.dataTables_buttons {
|
221
|
+
.buttons-bulk-actions {
|
222
|
+
button { font-size: 12px; }
|
223
|
+
}
|
224
|
+
}
|
@@ -5,7 +5,7 @@ module Effective
|
|
5
5
|
# This will respond to both a GET and a POST
|
6
6
|
def show
|
7
7
|
begin
|
8
|
-
@datatable =
|
8
|
+
@datatable = EffectiveDatatables.find(params[:id], params[:attributes])
|
9
9
|
@datatable.view = view_context
|
10
10
|
|
11
11
|
EffectiveDatatables.authorize!(self, :index, @datatable.collection_class)
|
@@ -13,18 +13,51 @@ module Effective
|
|
13
13
|
render json: @datatable.to_json
|
14
14
|
rescue => e
|
15
15
|
EffectiveDatatables.authorized?(self, :index, @datatable.try(:collection_class))
|
16
|
-
|
17
16
|
render json: error_json(e)
|
17
|
+
|
18
|
+
ExceptionNotifier.notify_exception(e) if defined?(ExceptionNotifier)
|
19
|
+
raise e if Rails.env.development?
|
18
20
|
end
|
19
21
|
end
|
20
22
|
|
21
|
-
|
23
|
+
def reorder
|
24
|
+
begin
|
25
|
+
@datatable = EffectiveDatatables.find(params[:id], params[:attributes])
|
26
|
+
@datatable.view = view_context
|
27
|
+
|
28
|
+
EffectiveDatatables.authorize!(self, :index, @datatable.collection_class)
|
29
|
+
|
30
|
+
@resource = @datatable.collection.find(params[:reorder][:id])
|
31
|
+
|
32
|
+
EffectiveDatatables.authorize!(self, :update, @resource)
|
33
|
+
|
34
|
+
attribute = @datatable.columns[:_reorder][:reorder]
|
35
|
+
old_index = params[:reorder][:old].to_i
|
36
|
+
new_index = params[:reorder][:new].to_i
|
37
|
+
|
38
|
+
@resource.class.transaction do
|
39
|
+
if new_index > old_index
|
40
|
+
@datatable.collection.where("#{attribute} > ? AND #{attribute} <= ?", old_index, new_index).update_all("#{attribute} = #{attribute} - 1")
|
41
|
+
@resource.update_column(attribute, new_index)
|
42
|
+
end
|
43
|
+
|
44
|
+
if old_index > new_index
|
45
|
+
@datatable.collection.where("#{attribute} >= ? AND #{attribute} < ?", new_index, old_index).update_all("#{attribute} = #{attribute} + 1")
|
46
|
+
@resource.update_column(attribute, new_index)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
render status: :ok, body: :ok
|
51
|
+
rescue Effective::AccessDenied => e
|
52
|
+
render(status: :unauthorized, body: 'Access Denied')
|
53
|
+
rescue => e
|
54
|
+
render(status: :error, body: 'Unexpected Error')
|
55
|
+
end
|
22
56
|
|
23
|
-
def find_datatable(id)
|
24
|
-
id = id.to_s.gsub(/-\d+\z/, '').gsub('-', '/')
|
25
|
-
id.classify.safe_constantize || id.classify.pluralize.safe_constantize
|
26
57
|
end
|
27
58
|
|
59
|
+
private
|
60
|
+
|
28
61
|
def error_json(e)
|
29
62
|
{
|
30
63
|
data: [],
|
@@ -0,0 +1,47 @@
|
|
1
|
+
class EffectiveStyleGuideDatatable < Effective::Datatable
|
2
|
+
datatable do
|
3
|
+
length 10
|
4
|
+
|
5
|
+
col :id
|
6
|
+
col :material, search: { collection: ['Stainless Steel', 'Copper', 'Cast Iron', 'Composite'] }
|
7
|
+
col :bowl, search: { collection: ['Single Bowl', 'Double Bowl', 'Triple Bowl'] }
|
8
|
+
col :name
|
9
|
+
col :date, as: :date
|
10
|
+
|
11
|
+
actions_col
|
12
|
+
end
|
13
|
+
|
14
|
+
# Set the permission check to the same as Effective::StyleGuide
|
15
|
+
def collection_class
|
16
|
+
defined?(Effective::StyleGuide) ? Effective::StyleGuide : super
|
17
|
+
end
|
18
|
+
|
19
|
+
collection do
|
20
|
+
now = Time.zone.now
|
21
|
+
[
|
22
|
+
[1, 'Stainless Steel', 'Single Bowl', 'KOHLER Staccato', (now + 1.day)],
|
23
|
+
[2, 'Stainless Steel', 'Double Bowl', 'KOHLER Vault Undercounter', (now + 1.day)],
|
24
|
+
[3, 'Stainless Steel', 'Triple Bowl', 'KRAUS All-In-One', (now + 1.day)],
|
25
|
+
[4, 'Stainless Steel', 'Single Bowl', 'KOHLER Vault Dual Mount', (now + 1.day)],
|
26
|
+
[5, 'Stainless Steel', 'Single Bowl', 'KRAUS All-In-One Undermount', (now + 2.days)],
|
27
|
+
[6, 'Stainless Steel', 'Double Bowl', 'Glacier Bay All-in-One', (now + 2.days)],
|
28
|
+
[7, 'Stainless Steel', 'Single Bowl', 'Elkay Neptune', (now + 2.days)],
|
29
|
+
[8, 'Copper', 'Single Bowl', 'ECOSINKS Apron Front Dual Mount', (now + 2.days)],
|
30
|
+
[9, 'Copper', 'Double Bowl', 'ECOSINKS Dual Mount Front Hammered', (now + 2.days)],
|
31
|
+
[10, 'Copper', 'Triple Bowl', 'Glarier Bay Undermount', (now + 3.days)],
|
32
|
+
[11, 'Copper', 'Single Bowl', 'Whitehaus Undermount', (now + 3.days)],
|
33
|
+
[12, 'Copper', 'Double Bowl', 'Belle Foret Apron Front', (now + 3.days)],
|
34
|
+
[13, 'Copper', 'Double Bowl', 'Pegasus Dual Mount', (now + 3.days)],
|
35
|
+
[14, 'Cast Iron', 'Double Bowl', 'KOHLER Whitehaven', (now + 3.days)],
|
36
|
+
[15, 'Cast Iron', 'Triple Bowl', 'KOHLER Hartland', (now + 3.days)],
|
37
|
+
[16, 'Cast Iron', 'Single Bowl', 'KOHLER Cape Dory Undercounter', (now + 4.days)],
|
38
|
+
[17, 'Cast Iron', 'Double Bowl', 'KOLER Bakersfield', (now + 4.days)],
|
39
|
+
[18, 'Cast Iron', 'Double Bowl', 'American Standard Offset', (now + 4.days)],
|
40
|
+
[19, 'Cast Iron', 'Single Bowl', 'Brookfield Top', (now + 4.days)],
|
41
|
+
[20, 'Composite', 'Single Bowl', 'Blanco Diamond Undermount', (now + 5.days)],
|
42
|
+
[21, 'Composite', 'Double Bowl', 'Mont Blanc Waterbrook', (now + 5.days)],
|
43
|
+
[22, 'Composite', 'Triple Bowl', 'Pegasus Triple Mount', (now + 5.days)],
|
44
|
+
[23, 'Composite', 'Single Bowl', 'Swanstone Dual Mount', (now + 5.days)]
|
45
|
+
]
|
46
|
+
end
|
47
|
+
end
|
@@ -1,8 +1,15 @@
|
|
1
1
|
# These are expected to be called by a developer. They are part of the datatables DSL.
|
2
2
|
module EffectiveDatatablesHelper
|
3
|
-
|
4
|
-
def render_datatable(datatable, input_js: {}, buttons: true, charts: true, filters: true, simple: false)
|
3
|
+
def render_datatable(datatable, input_js: {}, buttons: true, charts: true, entries: true, filters: true, inline: false, pagination: true, search: true, simple: false, sort: true)
|
5
4
|
raise 'expected datatable to be present' unless datatable
|
5
|
+
raise 'expected input_js to be a Hash' unless input_js.kind_of?(Hash)
|
6
|
+
|
7
|
+
if simple
|
8
|
+
buttons = charts = entries = filters = pagination = search = sort = false
|
9
|
+
end
|
10
|
+
|
11
|
+
datatable.attributes[:inline] = true if inline
|
12
|
+
datatable.attributes[:sortable] = false unless sort
|
6
13
|
|
7
14
|
datatable.view ||= self
|
8
15
|
|
@@ -13,31 +20,48 @@ module EffectiveDatatablesHelper
|
|
13
20
|
charts = charts && datatable._charts.present?
|
14
21
|
filters = filters && (datatable._scopes.present? || datatable._filters.present?)
|
15
22
|
|
16
|
-
datatable.
|
17
|
-
|
23
|
+
html_class = ['effective-datatable', datatable.html_class, ('hide-sort' unless sort), ('hide-search' unless search), ('hide-buttons' unless buttons)].compact.join(' ')
|
24
|
+
|
25
|
+
if datatable.reorder? && !buttons
|
26
|
+
buttons = true; input_js[:buttons] = false
|
27
|
+
end
|
28
|
+
|
29
|
+
# Build the datatables DOM option
|
30
|
+
input_js[:dom] ||= [
|
31
|
+
("<'row'<'col-sm-12 dataTables_buttons'B>>" if buttons),
|
32
|
+
"<'row'<'col-sm-12'tr>>",
|
33
|
+
("<'row'" if entries || pagination),
|
34
|
+
("<'col-sm-6 dataTables_entries'il>" if entries),
|
35
|
+
("<'col-sm-6'p>" if pagination),
|
36
|
+
(">" if entries || pagination)
|
37
|
+
].compact.join
|
18
38
|
|
19
39
|
effective_datatable_params = {
|
20
40
|
id: datatable.to_param,
|
21
|
-
class:
|
41
|
+
class: html_class,
|
22
42
|
data: {
|
43
|
+
'attributes' => EffectiveDatatables.encrypt(datatable.attributes),
|
23
44
|
'authenticity-token' => form_authenticity_token,
|
24
|
-
'effective-form-inputs' => defined?(EffectiveFormInputs),
|
25
45
|
'bulk-actions' => datatable_bulk_actions(datatable),
|
26
46
|
'columns' => datatable_columns(datatable),
|
27
|
-
'cookie' => datatable.cookie_key,
|
28
47
|
'display-length' => datatable.display_length,
|
29
|
-
'display-order' =>
|
48
|
+
'display-order' => datatable_display_order(datatable),
|
30
49
|
'display-records' => datatable.to_json[:recordsFiltered],
|
31
50
|
'display-start' => datatable.display_start,
|
32
|
-
'
|
33
|
-
'
|
34
|
-
'
|
51
|
+
'inline' => inline.to_s,
|
52
|
+
'language' => EffectiveDatatables.language(I18n.locale),
|
53
|
+
'options' => input_js.to_json,
|
54
|
+
'reset' => (datatable_reset(datatable) if search),
|
55
|
+
'reorder' => datatable_reorder(datatable),
|
56
|
+
'reorder-index' => (datatable.columns[:_reorder][:index] if datatable.reorder?).to_s,
|
57
|
+
'simple' => simple.to_s,
|
58
|
+
'spinner' => '', # effective_bootstrap
|
35
59
|
'source' => effective_datatables.datatable_path(datatable, {format: 'json'}),
|
36
60
|
'total-records' => datatable.to_json[:recordsTotal]
|
37
61
|
}
|
38
62
|
}
|
39
63
|
|
40
|
-
if (charts || filters)
|
64
|
+
if (charts || filters)
|
41
65
|
output = ''.html_safe
|
42
66
|
|
43
67
|
if charts
|
@@ -60,59 +84,28 @@ module EffectiveDatatablesHelper
|
|
60
84
|
end
|
61
85
|
end
|
62
86
|
|
63
|
-
def
|
64
|
-
|
65
|
-
|
66
|
-
datatable.view ||= self
|
67
|
-
|
68
|
-
unless EffectiveDatatables.authorized?(controller, :index, datatable.collection_class)
|
69
|
-
return content_tag(:p, "You are not authorized to view this datatable. (cannot :index, #{datatable.collection_class})")
|
70
|
-
end
|
71
|
-
|
72
|
-
effective_datatable_params = {
|
73
|
-
id: datatable.to_param,
|
74
|
-
class: Array(datatable.table_html_class).join(' '),
|
75
|
-
data: {}
|
76
|
-
}
|
77
|
-
|
78
|
-
render(partial: 'effective/datatables/datatable',
|
79
|
-
locals: { datatable: datatable, effective_datatable_params: effective_datatable_params }
|
80
|
-
)
|
87
|
+
def render_inline_datatable(datatable)
|
88
|
+
render_datatable(datatable, inline: true)
|
81
89
|
end
|
82
90
|
|
83
|
-
def
|
84
|
-
|
85
|
-
|
86
|
-
datatable.view ||= self
|
87
|
-
return unless datatable._scopes.present? || datatable._filters.present?
|
88
|
-
|
89
|
-
if datatable._filters_form_required?
|
90
|
-
render partial: 'effective/datatables/filters', locals: { datatable: datatable }
|
91
|
-
else
|
92
|
-
render(partial: 'effective/datatables/filters', locals: { datatable: datatable }).gsub('<form', '<div').gsub('/form>', '/div>').html_safe
|
93
|
-
end
|
94
|
-
|
91
|
+
def render_simple_datatable(datatable)
|
92
|
+
render_datatable(datatable, simple: true)
|
95
93
|
end
|
96
94
|
|
97
|
-
def
|
98
|
-
|
99
|
-
|
100
|
-
datatable.view ||= self
|
101
|
-
return unless datatable._charts.present?
|
102
|
-
|
103
|
-
datatable._charts.map { |name, _| render_datatable_chart(datatable, name) }.join.html_safe
|
95
|
+
def inline_datatable?
|
96
|
+
params[:_datatable_id].present? && params[:_datatable_attributes].present?
|
104
97
|
end
|
105
98
|
|
106
|
-
def
|
107
|
-
|
99
|
+
def inline_datatable
|
100
|
+
return nil unless inline_datatable?
|
101
|
+
return @_inline_datatable if @_inline_datatable
|
108
102
|
|
109
|
-
datatable.
|
110
|
-
|
103
|
+
datatable = EffectiveDatatables.find(params[:_datatable_id], params[:_datatable_attributes])
|
104
|
+
datatable.view = self
|
111
105
|
|
112
|
-
|
113
|
-
chart_data = datatable.to_json[:charts][name][:data]
|
106
|
+
EffectiveDatatables.authorize!(self, :index, datatable.collection_class)
|
114
107
|
|
115
|
-
|
108
|
+
@_inline_datatable ||= datatable
|
116
109
|
end
|
117
110
|
|
118
111
|
end
|
@@ -1,21 +1,21 @@
|
|
1
1
|
# These aren't expected to be called by a developer. They are internal methods.
|
2
|
+
# These aren't expected to be called by a developer. They are internal methods.
|
2
3
|
module EffectiveDatatablesPrivateHelper
|
3
4
|
|
4
5
|
# https://datatables.net/reference/option/columns
|
5
6
|
def datatable_columns(datatable)
|
6
|
-
|
7
|
-
simple_form_for(:datatable_search, url: '#', html: {id: "#{datatable.to_param}-form"}) { |f| form = f }
|
7
|
+
sortable = datatable.sortable?
|
8
8
|
|
9
9
|
datatable.columns.map do |name, opts|
|
10
10
|
{
|
11
|
-
name: name,
|
12
|
-
title: content_tag(:span, (opts[:label] == false ? '' : opts[:label]), class: 'search-label'),
|
13
11
|
className: opts[:col_class],
|
14
|
-
|
12
|
+
name: name,
|
15
13
|
responsivePriority: opts[:responsive],
|
16
14
|
search: datatable.state[:search][name],
|
17
|
-
|
18
|
-
|
15
|
+
searchHtml: datatable_search_tag(datatable, name, opts),
|
16
|
+
sortable: (opts[:sort] && sortable),
|
17
|
+
title: datatable_label_tag(datatable, name, opts),
|
18
|
+
visible: datatable.state[:visible][name]
|
19
19
|
}
|
20
20
|
end.to_json.html_safe
|
21
21
|
end
|
@@ -26,17 +26,71 @@ module EffectiveDatatablesPrivateHelper
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
+
def datatable_display_order(datatable)
|
30
|
+
(datatable.sortable? ? [datatable.order_index, datatable.order_direction] : false).to_json.html_safe
|
31
|
+
end
|
32
|
+
|
29
33
|
def datatable_reset(datatable)
|
30
|
-
|
34
|
+
link_to(content_tag(:span, t('effective_datatables.reset')), '#', class: 'btn btn-link btn-sm buttons-reset-search')
|
35
|
+
end
|
36
|
+
|
37
|
+
def datatable_reorder(datatable)
|
38
|
+
return unless datatable.reorder? && EffectiveDatatables.authorized?(self, :update, datatable.collection_class)
|
39
|
+
link_to(content_tag(:span, t('effective_datatables.reorder')), '#', class: 'btn btn-link btn-sm buttons-reorder', disabled: true)
|
31
40
|
end
|
32
41
|
|
33
|
-
def
|
42
|
+
def datatable_new_resource_button(datatable, name, column)
|
43
|
+
return unless column[:inline] && (column[:actions][:new] != false)
|
44
|
+
|
45
|
+
action = { action: :new, class: ['btn', column[:btn_class].presence].compact.join(' '), 'data-remote': true }
|
46
|
+
|
47
|
+
if column[:actions][:new].kind_of?(Hash) # This might be active_record_array_collection?
|
48
|
+
action = action.merge(column[:actions][:new])
|
49
|
+
|
50
|
+
effective_resource = (datatable.effective_resource || datatable.fallback_effective_resource)
|
51
|
+
klass = (column[:actions][:new][:klass] || effective_resource&.klass || datatable.collection_class)
|
52
|
+
elsif Array(datatable.effective_resource&.actions).include?(:new)
|
53
|
+
effective_resource = datatable.effective_resource
|
54
|
+
klass = effective_resource.klass
|
55
|
+
else
|
56
|
+
return
|
57
|
+
end
|
58
|
+
|
59
|
+
# Will only work if permitted
|
60
|
+
render_resource_actions(klass, actions: { t('effective_datatables.new') => action }, effective_resource: effective_resource)
|
61
|
+
end
|
62
|
+
|
63
|
+
def datatable_label_tag(datatable, name, opts)
|
64
|
+
case opts[:as]
|
65
|
+
when :actions
|
66
|
+
content_tag(:span, t('effective_datatables.actions'), style: 'display: none;')
|
67
|
+
when :bulk_actions
|
68
|
+
content_tag(:span, t('effective_datatables.bulk_actions'), style: 'display: none;')
|
69
|
+
when :reorder
|
70
|
+
content_tag(:span, t('effective_datatables.reorder'), style: 'display: none;')
|
71
|
+
else
|
72
|
+
content_tag(:span, opts[:label].presence)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def datatable_search_tag(datatable, name, opts)
|
77
|
+
return datatable_new_resource_button(datatable, name, opts) if name == :_actions
|
78
|
+
|
79
|
+
return if opts[:search] == false
|
80
|
+
|
81
|
+
# Build the search
|
82
|
+
@_effective_datatables_form_builder || simple_form_for(:datatable_search, url: '#', html: {id: "#{datatable.to_param}-form"}) { |f| @_effective_datatables_form_builder = f }
|
83
|
+
form = @_effective_datatables_form_builder
|
84
|
+
|
34
85
|
include_blank = opts[:search].key?(:include_blank) ? opts[:search][:include_blank] : opts[:label]
|
35
86
|
pattern = opts[:search][:pattern]
|
36
87
|
placeholder = opts[:search][:placeholder] || ''
|
37
88
|
title = opts[:search][:title] || opts[:label]
|
38
89
|
wrapper_html = { class: 'datatable_search' }
|
39
90
|
|
91
|
+
collection = opts[:search].delete(:collection)
|
92
|
+
value = datatable.state[:search][name]
|
93
|
+
|
40
94
|
input_html = {
|
41
95
|
name: nil,
|
42
96
|
value: value,
|
@@ -83,7 +137,7 @@ module EffectiveDatatablesPrivateHelper
|
|
83
137
|
when :select, :boolean
|
84
138
|
form.input name, label: false, required: false, value: value,
|
85
139
|
as: (ActionView::Helpers::FormBuilder.instance_methods.include?(:effective_select) ? :effective_select : :select),
|
86
|
-
collection:
|
140
|
+
collection: collection,
|
87
141
|
selected: opts[:search][:value],
|
88
142
|
multiple: opts[:search][:multiple],
|
89
143
|
grouped: opts[:search][:grouped],
|
@@ -102,4 +156,76 @@ module EffectiveDatatablesPrivateHelper
|
|
102
156
|
end
|
103
157
|
end
|
104
158
|
|
105
|
-
|
159
|
+
def render_datatable_filters(datatable)
|
160
|
+
raise 'expected datatable to be present' unless datatable
|
161
|
+
|
162
|
+
datatable.view ||= self
|
163
|
+
return unless datatable._scopes.present? || datatable._filters.present?
|
164
|
+
|
165
|
+
if datatable._filters_form_required?
|
166
|
+
render partial: 'effective/datatables/filters', locals: { datatable: datatable }
|
167
|
+
else
|
168
|
+
render(partial: 'effective/datatables/filters', locals: { datatable: datatable }).gsub('<form', '<div').gsub('/form>', '/div>').html_safe
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
def datatable_filter_tag(form, datatable, name, opts)
|
174
|
+
as = opts[:as].to_s.chomp('_field').to_sym
|
175
|
+
value = datatable.state[:filter][name]
|
176
|
+
collection = opts[:collection]
|
177
|
+
input_html = opts[:input_html] || {}
|
178
|
+
|
179
|
+
binding.pry
|
180
|
+
|
181
|
+
form.input name,
|
182
|
+
value: value,
|
183
|
+
selected: value,
|
184
|
+
as: as,
|
185
|
+
collection: collection,
|
186
|
+
label: opts[:label],
|
187
|
+
required: input_html.delete(:required),
|
188
|
+
multiple: input_html.delete(:multiple),
|
189
|
+
include_blank: input_html.delete(:include_blank),
|
190
|
+
group_method: input_html.delete(:group_method),
|
191
|
+
group_label_method: input_html.delete(:group_label_method),
|
192
|
+
value_method: input_html.delete(:value_method),
|
193
|
+
label_method: input_html.delete(:label_method),
|
194
|
+
input_html: (({name: ''} unless datatable._filters_form_required?) || {}).merge(input_html),
|
195
|
+
input_js: ({ placeholder: ''} if as == :effective_select),
|
196
|
+
wrapper_html: {class: 'form-group-sm'}
|
197
|
+
end
|
198
|
+
|
199
|
+
def datatable_scope_tag(form, datatable, opts = {})
|
200
|
+
collection = datatable._scopes.map { |name, opts| [opts[:label], name] }
|
201
|
+
value = datatable.state[:scope]
|
202
|
+
|
203
|
+
form.input :scope, label: false, required: false, checked: value,
|
204
|
+
as: (defined?(EffectiveFormInputs) ? :effective_radio_buttons : :radio_buttons),
|
205
|
+
collection: collection,
|
206
|
+
buttons: true,
|
207
|
+
wrapper_html: {class: 'btn-group-sm'}
|
208
|
+
end
|
209
|
+
|
210
|
+
def render_datatable_charts(datatable)
|
211
|
+
raise 'expected datatable to be present' unless datatable
|
212
|
+
|
213
|
+
datatable.view ||= self
|
214
|
+
return unless datatable._charts.present?
|
215
|
+
|
216
|
+
datatable._charts.map { |name, _| render_datatable_chart(datatable, name) }.join.html_safe
|
217
|
+
end
|
218
|
+
|
219
|
+
def render_datatable_chart(datatable, name)
|
220
|
+
raise 'expected datatable to be present' unless datatable
|
221
|
+
|
222
|
+
datatable.view ||= self
|
223
|
+
return unless datatable._charts[name].present?
|
224
|
+
|
225
|
+
chart = datatable._charts[name]
|
226
|
+
chart_data = datatable.to_json[:charts][name][:data]
|
227
|
+
|
228
|
+
render partial: chart[:partial], locals: { datatable: datatable, chart: chart, chart_data: chart_data }
|
229
|
+
end
|
230
|
+
|
231
|
+
end
|