custom_table 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +210 -0
- data/Rakefile +8 -0
- data/app/assets/config/custom_table_manifest.js +1 -0
- data/app/assets/stylesheets/custom_table/application.scss +1 -0
- data/app/assets/stylesheets/custom_table/table.scss +89 -0
- data/app/controllers/concerns/custom_table_concern.rb +118 -0
- data/app/controllers/custom_table/application_controller.rb +4 -0
- data/app/controllers/custom_table/settings_controller.rb +86 -0
- data/app/helpers/custom_table/application_helper.rb +483 -0
- data/app/helpers/custom_table/fieldset_helper.rb +90 -0
- data/app/helpers/custom_table/icons_helper.rb +42 -0
- data/app/inputs/date_picker_input.rb +52 -0
- data/app/javascript/controllers/batch_actions_controller.js +53 -0
- data/app/javascript/controllers/table_controller.js +109 -0
- data/app/jobs/custom_table/application_job.rb +4 -0
- data/app/mailers/custom_table/application_mailer.rb +6 -0
- data/app/models/concerns/custom_table_settings.rb +42 -0
- data/app/models/custom_table/application_record.rb +5 -0
- data/app/views/custom_table/_download.haml +19 -0
- data/app/views/custom_table/_field.haml +8 -0
- data/app/views/custom_table/_field_plain.haml +1 -0
- data/app/views/custom_table/_fieldset.haml +2 -0
- data/app/views/custom_table/_filter.html.haml +104 -0
- data/app/views/custom_table/_settings.html.haml +57 -0
- data/app/views/custom_table/_table.html.haml +261 -0
- data/app/views/custom_table/_table.xlsx.axlsx +76 -0
- data/app/views/custom_table/_table_fe.xlsx.fast_excel +141 -0
- data/app/views/custom_table/_table_row.html.haml +72 -0
- data/app/views/custom_table/_table_row_data.html.haml +26 -0
- data/app/views/custom_table/settings/destroy.html.haml +4 -0
- data/app/views/custom_table/settings/edit.html.haml +2 -0
- data/app/views/custom_table/settings/update.html.haml +4 -0
- data/app/views/layouts/custom_table/application.html.erb +15 -0
- data/config/initializers/simple_form_bootstrap.rb +468 -0
- data/config/locales/en.yml +18 -0
- data/config/locales/ru.yml +18 -0
- data/config/routes.rb +5 -0
- data/lib/custom_table/configuration.rb +10 -0
- data/lib/custom_table/engine.rb +12 -0
- data/lib/custom_table/version.rb +3 -0
- data/lib/custom_table.rb +14 -0
- data/lib/generators/custom_table/USAGE +8 -0
- data/lib/generators/custom_table/custom_table_generator.rb +16 -0
- data/lib/generators/custom_table/templates/initializer.rb +3 -0
- data/lib/generators/custom_table/templates/migration.rb +5 -0
- data/lib/tasks/custom_table_tasks.rake +4 -0
- metadata +300 -0
@@ -0,0 +1,261 @@
|
|
1
|
+
- model_class = local_assigns[:model_class].presence || collection.model
|
2
|
+
- global_model_name = model_class.model_name.singular
|
3
|
+
- fields_totals = {}
|
4
|
+
- variant = local_assigns[:variant]
|
5
|
+
- if local_assigns[:tree] && local_assigns[:paginate]
|
6
|
+
%p.text-danger Tree mode is incompartible with pagination
|
7
|
+
|
8
|
+
- if collection.respond_to?(:model)
|
9
|
+
- customization = custom_table_user_customization_for(collection.model, variant)
|
10
|
+
- per_page = params[:per] || customization&.dig(:per_page).presence || 25
|
11
|
+
- collection = collection.page(params[:page]).per(per_page) if local_assigns[:paginate]
|
12
|
+
- collection = collection.without_count if !local_assigns[:last_page] # Disable Last Page for performance
|
13
|
+
|
14
|
+
- local_assigns[:fields] = params[:fields].split(",").map { |x| x.to_sym } if local_assigns[:fields].nil? && !params[:fields].blank?
|
15
|
+
- local_assigns[:skip_actions] = true if local_assigns[:skip_actions].nil? && params[:skip_actions].to_s=="true"
|
16
|
+
|
17
|
+
- fields = custom_table_fields_for(model_class, variant: variant, predefined_fields: local_assigns[:fields])
|
18
|
+
|
19
|
+
- fields = fields.except(*local_assigns[:skip_fields]) if !local_assigns[:skip_fields].nil?
|
20
|
+
|
21
|
+
%div.table-wrapper{data: {controller: "batch-actions"}}
|
22
|
+
|
23
|
+
- if local_assigns[:batch_actions]
|
24
|
+
= self.send(local_assigns[:batch_actions])
|
25
|
+
|
26
|
+
%table{class: ["search-fields", "custom-table", "table", "table-hover", "table-sm", model_class.model_name.plural], data: {controller: "table toggle"}}
|
27
|
+
%thead.sticky
|
28
|
+
- if local_assigns[:quick_filter]
|
29
|
+
%tr
|
30
|
+
%td{colspan: "100%"}
|
31
|
+
.input-group.input-group-sm
|
32
|
+
.input-group-text
|
33
|
+
= custom_table_search_icon
|
34
|
+
%input.form-control-sm.form-control{type: "text", data: {action: "table#search"}, placeholder: t("custom_table.quick_search")}
|
35
|
+
|
36
|
+
|
37
|
+
%tr
|
38
|
+
|
39
|
+
- if local_assigns[:tree]
|
40
|
+
%th{style: "width: 15px;"}
|
41
|
+
|
42
|
+
- if local_assigns[:with_select]
|
43
|
+
%th.checkbox-col
|
44
|
+
= check_box_tag "check-all", "", true, data: {"toggle-target": "toggler", "action": "toggle#toggle batch-actions#refresh"}
|
45
|
+
- if local_assigns[:with_index]
|
46
|
+
%th= "#"
|
47
|
+
- fields.each do |field, defs|
|
48
|
+
- next if defs[:table] == false
|
49
|
+
- cls = [field.to_s]
|
50
|
+
- defs[:amount] = true if defs[:amount].nil? && !model_class.columns_hash[field.to_s].nil? && [:float, :decimal, :integer].include?(model_class.columns_hash[field.to_s].type) && !model_class.defined_enums.has_key?(field.to_s)
|
51
|
+
- cls += ["text-end"] if defs[:amount]
|
52
|
+
%th{class: cls}
|
53
|
+
- if !defs[:sort].nil? && !@q.nil?
|
54
|
+
- defs[:sort] = {} if defs[:sort]===true
|
55
|
+
- sort_field = defs[:sort][:field].blank? ? field : defs[:sort][:field]
|
56
|
+
- sort_order = defs[:sort][:default_order].blank? ? :asc : defs[:sort][:default_order]
|
57
|
+
- if !@q.nil?
|
58
|
+
= sort_link @q, sort_field, default_order: sort_order, data: {sort: "custom-table-sort-#{sort_field}-#{sort_order}"} do
|
59
|
+
= defs[:label].nil? ? model_class.human_attribute_name(field) : defs[:label]
|
60
|
+
- else
|
61
|
+
= defs[:label].nil? ? model_class.human_attribute_name(field) : defs[:label]
|
62
|
+
|
63
|
+
- if !local_assigns[:skip_actions]
|
64
|
+
%th.text-end
|
65
|
+
|
66
|
+
%tbody
|
67
|
+
|
68
|
+
- position = 0
|
69
|
+
|
70
|
+
- if local_assigns[:tree]
|
71
|
+
|
72
|
+
- if collection.length > 0
|
73
|
+
|
74
|
+
- grouped_collection = collection.group_by{|i| i.parent_id}
|
75
|
+
|
76
|
+
- if !grouped_collection[nil].nil?
|
77
|
+
|
78
|
+
- grouped_collection[nil].each do |parent_item|
|
79
|
+
|
80
|
+
- childs = grouped_collection[parent_item.id] || []
|
81
|
+
|
82
|
+
= render "custom_table/table_row", local_assigns.merge({item: parent_item, fields: fields, position: position, fields_totals: fields_totals, has_children: (childs.length > 0)})
|
83
|
+
- position+=1
|
84
|
+
|
85
|
+
- childs.each do |item|
|
86
|
+
- position+=1
|
87
|
+
= render "custom_table/table_row", local_assigns.merge({item: item, fields: fields, position: position, fields_totals: fields_totals})
|
88
|
+
|
89
|
+
- elsif local_assigns[:group_by]
|
90
|
+
|
91
|
+
- if collection.length > 0
|
92
|
+
|
93
|
+
- grouped_collection = collection.group_by{|i| self.send(local_assigns[:group_by], i)}
|
94
|
+
|
95
|
+
-# - (grouped_collection[nil] || []).each do |ungrouped_items|
|
96
|
+
-# - ungrouped_items.each do |item|
|
97
|
+
-# - position+=1
|
98
|
+
-# = render "custom_table/table_row", local_assigns.merge({item: item, fields: fields, position: position, fields_totals: fields_totals})
|
99
|
+
|
100
|
+
-# - abort Hash[grouped_collection.sort_by{|k,v| k.to_s}].inspect
|
101
|
+
|
102
|
+
- group_id = 0
|
103
|
+
|
104
|
+
- Hash[grouped_collection.sort_by{|k,v| k.to_s}].each do |group, items|
|
105
|
+
|
106
|
+
- if !group.nil?
|
107
|
+
|
108
|
+
- group_id += 1
|
109
|
+
|
110
|
+
-# Calculating group totals
|
111
|
+
- group_fields_totals = {}
|
112
|
+
|
113
|
+
- items.each do |item|
|
114
|
+
- custom_table_fields_totals(fields: fields, item: item, totals: local_assigns[:totals], variant: variant, fields_totals: group_fields_totals)
|
115
|
+
%tr
|
116
|
+
- shown = false
|
117
|
+
- fields.each do |field, defs|
|
118
|
+
- next if defs[:table] == false
|
119
|
+
- if !group_fields_totals[field].nil?
|
120
|
+
%th{class: [field.to_s, "text-end"]}
|
121
|
+
= amount_color group_fields_totals[field]
|
122
|
+
- else
|
123
|
+
%th{class: [field.to_s, "text-start"]}
|
124
|
+
- if !shown
|
125
|
+
= tree_opener(group_id, true, local_assigns[:expanded])
|
126
|
+
= group
|
127
|
+
- shown = true
|
128
|
+
- if !local_assigns[:skip_actions]
|
129
|
+
%th.text-end
|
130
|
+
|
131
|
+
- items.each do |item|
|
132
|
+
- position+=1
|
133
|
+
= render "custom_table/table_row", local_assigns.merge({item: item, fields: fields, position: position, fields_totals: fields_totals, grouped_by_id: group_id})
|
134
|
+
|
135
|
+
- else
|
136
|
+
|
137
|
+
- collection.each do |item|
|
138
|
+
|
139
|
+
- position+=1
|
140
|
+
|
141
|
+
= render "custom_table/table_row", local_assigns.merge({item: item, fields: fields, position: position, fields_totals: fields_totals})
|
142
|
+
|
143
|
+
-# - model_name = item.model_name.singular # Allows to show different class models in one table!
|
144
|
+
-# -# = render partial: "custom_tables/table_row", locals: local_assigns.merge(item: item, position: position, fields: fields, fields_totals: fields_totals)
|
145
|
+
-# - row_class = local_assigns[:row_class] || "#{model_name}_row_class"
|
146
|
+
-# %tr{id: dom_id(item, "row"), :class => (self.send(row_class, item) rescue "")}
|
147
|
+
|
148
|
+
-# - if local_assigns[:with_select]
|
149
|
+
-# %td.checkbox-col
|
150
|
+
-# = self.send(local_assigns[:with_select], item, position)
|
151
|
+
|
152
|
+
-# - if local_assigns[:with_index]
|
153
|
+
-# %td
|
154
|
+
-# = position
|
155
|
+
|
156
|
+
-# - fields.each do |field, defs|
|
157
|
+
-# - next if defs[:table] == false
|
158
|
+
-# - td_classes = [field.to_s]
|
159
|
+
-# - td_classes += ["text-end"] if defs[:amount]
|
160
|
+
-# - td_classes += ["text-nowrap"] if defs[:nowrap]
|
161
|
+
-# - td_classes += ["amount"] if defs[:amount]
|
162
|
+
|
163
|
+
-# %td{class: td_classes, id: dom_id(item, field)}
|
164
|
+
-# - v = field_value_for(item, field, definitions: defs, variant: variant)
|
165
|
+
|
166
|
+
-# - if totals.has_key?(field) && totals[field].nil? # Auto-counting
|
167
|
+
-# - fields_totals[field] = 0 if fields_totals[field].nil?
|
168
|
+
-# - fields_totals[field] += raw_field_value_for(item, field, definitions: defs, variant: variant).to_f rescue 0
|
169
|
+
|
170
|
+
-# - if defs[:editable]
|
171
|
+
|
172
|
+
-# = editable item, field do
|
173
|
+
-# - if defs[:link_to_show] == true && custom_table_has_show_route?(item) && can?(:show, item)
|
174
|
+
-# -# = link_to v, url_for(controller: controller_name, action: "show", id: item.to_param)
|
175
|
+
-# = link_to v, [namespace, item], data: {turbo: false}
|
176
|
+
-# - else
|
177
|
+
-# = v
|
178
|
+
-# - else
|
179
|
+
-# - if defs[:link_to_show] == true && custom_table_has_show_route?(item) && can?(:show, item)
|
180
|
+
-# -# = link_to v, url_for(controller: controller_name, action: "show", id: item.to_param)
|
181
|
+
-# = link_to v, [namespace, item], data: {turbo: false}
|
182
|
+
-# - else
|
183
|
+
-# = v
|
184
|
+
|
185
|
+
-# - if !local_assigns[:skip_actions]
|
186
|
+
|
187
|
+
-# %td.text-end.actions
|
188
|
+
-# - if !local_assigns[:actions].nil?
|
189
|
+
-# = self.send(local_assigns[:actions], item)
|
190
|
+
-# - elsif !variant.nil? && self.class.method_defined?("#{variant}_#{model_name}_custom_table_actions")
|
191
|
+
-# = self.send("#{variant}_#{model_name}_custom_table_actions", item)
|
192
|
+
-# - elsif self.class.method_defined?("#{model_name}_custom_table_actions")
|
193
|
+
-# = self.send("#{model_name}_custom_table_actions", item)
|
194
|
+
-# - if local_assigns[:skip_default_actions].nil?
|
195
|
+
-# - if (!custom_table_has_show_route?(item) || local_assigns[:force_edit_button]) && can?(:update, item)
|
196
|
+
-# = custom_table_edit_button [:edit, namespace, local_assigns[:parent], item], id: "edit_#{item.model_name.singular}_#{item.id}", modal: local_assigns[:modal_edit]
|
197
|
+
-# - if can? :destroy, item
|
198
|
+
-# - if (Rails.application.routes.recognize_path(url_for([namespace, local_assigns[:parent], item]), :method => :delete) rescue false)
|
199
|
+
-# = custom_table_delete_button [namespace, local_assigns[:parent], item], id: "destroy_#{item.model_name.singular}_#{item.id}"
|
200
|
+
|
201
|
+
- if local_assigns.has_key?(:extra) && !extra.nil?
|
202
|
+
- extra.each do |er|
|
203
|
+
%tr
|
204
|
+
- fields.each do |field, defs|
|
205
|
+
- next if defs[:table] == false
|
206
|
+
%td{class: [field.to_s]}
|
207
|
+
= er[field]
|
208
|
+
%td
|
209
|
+
|
210
|
+
- if collection.length == 0
|
211
|
+
%tr.warning.text-center
|
212
|
+
%th{:colspan=>"100%"}= t("custom_table.no_records_found")
|
213
|
+
- else
|
214
|
+
|
215
|
+
- found_totals = custom_table_totals(collection, fields, local_assigns[:totals], fields_totals)
|
216
|
+
|
217
|
+
- if !found_totals.empty?
|
218
|
+
|
219
|
+
%tr.totals{data: {"table-target": "move"}}
|
220
|
+
- if local_assigns[:tree]
|
221
|
+
%th
|
222
|
+
|
223
|
+
- if local_assigns[:with_index]
|
224
|
+
%th
|
225
|
+
|
226
|
+
- if local_assigns[:with_select]
|
227
|
+
%th
|
228
|
+
|
229
|
+
- fields.each do |field, defs|
|
230
|
+
- next if defs[:table] == false
|
231
|
+
%th{class: [field.to_s, "text-end"]}
|
232
|
+
- if !found_totals[field].nil?
|
233
|
+
- if found_totals[field].is_a?(Numeric)
|
234
|
+
= amount_color found_totals[field]
|
235
|
+
- else
|
236
|
+
= found_totals[field]
|
237
|
+
%th.text-end
|
238
|
+
|
239
|
+
- if collection.respond_to? :total_pages
|
240
|
+
.custom-table-pagination.overflow-hidden
|
241
|
+
-# - if turbo_frame_request?
|
242
|
+
-# - if !collection.last_page?
|
243
|
+
-# = link_to_next_page collection, raw(t('views.pagination.next'))
|
244
|
+
-# - else
|
245
|
+
|
246
|
+
- begin
|
247
|
+
- if collection.total_count > 25
|
248
|
+
%nav.float-end.ms-2
|
249
|
+
%ul.pagination
|
250
|
+
- [25, 50, 100].each do |p|
|
251
|
+
%li.page-item{class: (collection.limit_value.to_i == p) ? "active" : ""}
|
252
|
+
= link_to p, url_for(params.permit!.merge({per: p})), class: "page-link"
|
253
|
+
|
254
|
+
= paginate(collection, theme: 'bootstrap-5')
|
255
|
+
- rescue
|
256
|
+
= link_to_prev_page collection, t("views.pagination.previous").html_safe, class: "btn btn-outline-primary"
|
257
|
+
= link_to_next_page collection, t("views.pagination.next").html_safe, class: "btn btn-outline-primary"
|
258
|
+
|
259
|
+
-# - "TODO: Remove with param"
|
260
|
+
-# - if false && turbo_frame_request? && params[:q].present?
|
261
|
+
-# = link_to t("show_all"), url_for(q: params[:q]), data: {turbo: false}, class: "text-right"
|
@@ -0,0 +1,76 @@
|
|
1
|
+
global_model_name = collection.model.model_name.singular
|
2
|
+
|
3
|
+
sheet.add_row []
|
4
|
+
|
5
|
+
if local_assigns[:fields].nil?
|
6
|
+
fields = custom_table_fields_definition_for(collection.model)
|
7
|
+
else
|
8
|
+
d = custom_table_fields_definition_for(collection.model)
|
9
|
+
fields = {}
|
10
|
+
local_assigns[:fields].each do |f|
|
11
|
+
found = d.find {|k, v| k == f }
|
12
|
+
fields[f] = found[1] if !found.nil?
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
if defined?(style)
|
17
|
+
unless defined?(aligned_style)
|
18
|
+
aligned_style = style.add_style alignment: { horizontal: :left }
|
19
|
+
end
|
20
|
+
unless defined?(date_style)
|
21
|
+
date_style = style.add_style(format_code: 'dd.mm.yyyy', alignment: { horizontal: :left })
|
22
|
+
end
|
23
|
+
|
24
|
+
unless defined?(head_style)
|
25
|
+
head_style = s.add_style b: true, alignment: { horizontal: :left }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
head = []
|
30
|
+
fields.each do |field, defs|
|
31
|
+
next if defs[:table] == false
|
32
|
+
|
33
|
+
head.push defs[:label].nil? ? collection.model.human_attribute_name(field) : defs[:label]
|
34
|
+
end
|
35
|
+
|
36
|
+
if defined?(extra_head)
|
37
|
+
head += extra_head.call
|
38
|
+
end
|
39
|
+
|
40
|
+
sheet.add_row(head, style: head_style)
|
41
|
+
|
42
|
+
collection.except(:limit, :offset).find_each do |item|
|
43
|
+
row_def = []
|
44
|
+
row = []
|
45
|
+
style_def = []
|
46
|
+
|
47
|
+
model_name = item.model_name.singular # Allows to show different class models in one table!
|
48
|
+
|
49
|
+
fields.each do |field, defs|
|
50
|
+
next if defs[:table] == false
|
51
|
+
|
52
|
+
value = raw_field_value_for(item, field)
|
53
|
+
val_def = nil
|
54
|
+
val_style = aligned_style
|
55
|
+
|
56
|
+
if [Date, ActiveSupport::TimeWithZone].include?(value.class)
|
57
|
+
value = value.to_date
|
58
|
+
val_def = :date
|
59
|
+
val_style = date_style if defined?(date_style)
|
60
|
+
end
|
61
|
+
|
62
|
+
if [String].include?(value.class)
|
63
|
+
val_def = :string
|
64
|
+
end
|
65
|
+
|
66
|
+
row.push value
|
67
|
+
row_def.push val_def
|
68
|
+
style_def.push val_style
|
69
|
+
end
|
70
|
+
|
71
|
+
if defined?(extra_cols)
|
72
|
+
row += extra_cols.call(item)
|
73
|
+
end
|
74
|
+
|
75
|
+
sheet.add_row(row, style: aligned_style, types: row_def)
|
76
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
global_model_name = collection.model.model_name.singular
|
2
|
+
|
3
|
+
if local_assigns[:fields].nil?
|
4
|
+
if params[:all_fields].to_s == "true"
|
5
|
+
fields = custom_table_fields_definition_for(collection.model, local_assigns[:variant])
|
6
|
+
else
|
7
|
+
fields = custom_table_fields_for(collection.model, variant: local_assigns[:variant], predefined_fields: local_assigns[:fields])
|
8
|
+
end
|
9
|
+
else
|
10
|
+
fields = custom_table_fields_list_to_definitions(collection.model, fields)
|
11
|
+
end
|
12
|
+
|
13
|
+
data_start_row = sheet.last_row_number+1
|
14
|
+
data_end_row = collection.length + data_start_row + 3
|
15
|
+
|
16
|
+
if !local_assigns[:totals].nil?
|
17
|
+
data_start_row+=1
|
18
|
+
total_vals = []
|
19
|
+
total_format = workbook.number_format("#,##0.00").set(bold: true, align: {h: :right, v: :center})
|
20
|
+
|
21
|
+
i = 0
|
22
|
+
fields.each do |field, defs|
|
23
|
+
if totals.has_key?(field)
|
24
|
+
if total_vals.compact.length == 0 && total_vals.length > 0
|
25
|
+
total_vals[-1] = "Total:"
|
26
|
+
end
|
27
|
+
col = ("A".."Z").to_a[i]
|
28
|
+
if totals[field] == nil
|
29
|
+
total_vals.push FastExcel::Formula.new("SUM(#{col}#{data_start_row+2}:#{col}#{data_end_row})")
|
30
|
+
else
|
31
|
+
total_vals.push totals[field]
|
32
|
+
end
|
33
|
+
else
|
34
|
+
total_vals.push nil
|
35
|
+
end
|
36
|
+
i+=1
|
37
|
+
end
|
38
|
+
# abort total_vals.inspect
|
39
|
+
sheet.append_row(total_vals, total_format)
|
40
|
+
sheet.set_row(sheet.last_row_number, 20, nil)
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
head = []
|
46
|
+
head_formats = []
|
47
|
+
|
48
|
+
fields.each do |field, defs|
|
49
|
+
next if defs[:table] == false
|
50
|
+
head.push defs[:label].nil? ? collection.model.human_attribute_name(field) : defs[:label]
|
51
|
+
|
52
|
+
if local_assigns[:head_format].nil?
|
53
|
+
head_format = workbook.bold_format
|
54
|
+
else
|
55
|
+
head_format = sheet.workbook.add_format(local_assigns[:head_format])
|
56
|
+
end
|
57
|
+
|
58
|
+
if !local_assigns[:column_formats].nil? && !local_assigns[:column_formats][field.to_sym].nil?
|
59
|
+
head_format.set(local_assigns[:column_formats][field.to_sym])
|
60
|
+
end
|
61
|
+
head_formats.push(head_format)
|
62
|
+
end
|
63
|
+
|
64
|
+
fields.keys.each_with_index do |key, i|
|
65
|
+
w = 15
|
66
|
+
sheet.set_column(i, i, w)
|
67
|
+
end
|
68
|
+
|
69
|
+
if defined?(extra_head)
|
70
|
+
head += extra_head.call
|
71
|
+
end
|
72
|
+
|
73
|
+
# sheet.set_row(row_num = 1, 15, )
|
74
|
+
sheet.append_row(head, head_formats)
|
75
|
+
|
76
|
+
column_formats = {}
|
77
|
+
|
78
|
+
iterator = "find_each" if local_assigns[:iterator].nil?
|
79
|
+
|
80
|
+
collection.except(:limit, :offset).send(iterator) do |item|
|
81
|
+
|
82
|
+
row = []
|
83
|
+
formats = []
|
84
|
+
|
85
|
+
model_name = item.model_name.singular # Allows to show different class models in one table!
|
86
|
+
|
87
|
+
fields.each do |field, defs|
|
88
|
+
next if defs[:table] == false
|
89
|
+
|
90
|
+
value = raw_field_value_for(item, field)
|
91
|
+
|
92
|
+
if column_formats[field].nil?
|
93
|
+
|
94
|
+
if item.class.columns_hash[field.to_s] && item.class.columns_hash[field.to_s].type == :boolean
|
95
|
+
# Boolean
|
96
|
+
column_formats[field] = local_assigns[:generic_data_format]
|
97
|
+
elsif (defs[:type] == :date) || (item.class.columns_hash[field.to_s] && [:date, :datetime].include?(item.class.columns_hash[field.to_s].type))
|
98
|
+
value = value.to_date if !value.nil?
|
99
|
+
column_formats[field] = workbook.number_format("[$-409]dd/mm/yy;@").set(align: { h: :center })
|
100
|
+
elsif item.class.columns_hash[field.to_s] && [:integer, :float, :decimal].include?(item.class.columns_hash[field.to_s].type)
|
101
|
+
column_formats[field] = workbook.number_format("#,##0.00") if (defs[:amount]!=false)
|
102
|
+
elsif [Date, ActiveSupport::TimeWithZone].include?(value.class)
|
103
|
+
value = value.to_date if !value.nil?
|
104
|
+
column_formats[field] = workbook.number_format("[$-409]dd/mm/yy;@").set(align: { h: :center })
|
105
|
+
elsif defs[:amount] || value.is_a?(Numeric)
|
106
|
+
column_formats[field] = workbook.number_format("#,##0.00")
|
107
|
+
else
|
108
|
+
column_formats[field] = local_assigns[:generic_data_format]
|
109
|
+
end
|
110
|
+
|
111
|
+
if !local_assigns[:column_formats].nil? && !local_assigns[:column_formats][field.to_sym].nil?
|
112
|
+
column_formats[field].set(local_assigns[:column_formats][field.to_sym])
|
113
|
+
end
|
114
|
+
|
115
|
+
# abort value.inspect if field.to_s == "credit"
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
formats.push column_formats[field]
|
120
|
+
row.push value
|
121
|
+
end
|
122
|
+
|
123
|
+
if defined?(extra_cols)
|
124
|
+
row += extra_cols.call(item)
|
125
|
+
end
|
126
|
+
|
127
|
+
sheet.append_row(row, formats)
|
128
|
+
end
|
129
|
+
|
130
|
+
ef = workbook.add_format(top: :medium)
|
131
|
+
row = []
|
132
|
+
fields.each do |field, defs|
|
133
|
+
next if defs[:table] == false
|
134
|
+
row.push nil
|
135
|
+
end
|
136
|
+
sheet.append_row(row, ef)
|
137
|
+
|
138
|
+
|
139
|
+
if local_assigns[:autofilter]
|
140
|
+
sheet.autofilter(data_start_row, 0, sheet.last_row_number, fields.length-1)
|
141
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
- variant = local_assigns[:variant]
|
2
|
+
- model_name = item.model_name.singular # Allows to show different class models in one table!
|
3
|
+
-# = render partial: "custom_tables/table_row", locals: local_assigns.merge(item: item, position: position, fields: fields, fields_totals: fields_totals)
|
4
|
+
- row_class_helper = local_assigns[:row_class] || "#{model_name}_row_class"
|
5
|
+
- row_class = [(self.send(row_class_helper, item) rescue "")]
|
6
|
+
|
7
|
+
- row_class += ["child-of-#{item.parent_id}", (local_assigns[:expanded] ? "" : "d-none")] if local_assigns[:tree] && !item.parent_id.nil?
|
8
|
+
- row_class += ["child-of-#{local_assigns[:grouped_by_id]}", (local_assigns[:expanded] ? "" : "d-none")] if local_assigns[:grouped_by_id]
|
9
|
+
|
10
|
+
%tr{id: dom_id(item, "row"), :class => row_class}
|
11
|
+
|
12
|
+
- if local_assigns[:tree]
|
13
|
+
%td
|
14
|
+
- if item.parent_id.nil?
|
15
|
+
- if local_assigns[:has_children]
|
16
|
+
= tree_opener(item.id, local_assigns[:has_children], local_assigns[:expanded])
|
17
|
+
- else
|
18
|
+
= custom_table_icon(custom_table_tree_child_icon_class)
|
19
|
+
|
20
|
+
- if local_assigns[:with_select]
|
21
|
+
%td.checkbox-col
|
22
|
+
- if local_assigns[:with_select].to_s == "true"
|
23
|
+
= check_box_tag "#{item.model_name.plural}[]", item.id, (!params[item.model_name.plural.to_sym].blank?) && (params[item.model_name.plural.to_sym].include?(item.id.to_s)), data: {"toggle-target": "checkbox", "batch-actions-target": "checkbox", "action": "toggle#recalculateToggler batch-actions#refresh"}
|
24
|
+
- else
|
25
|
+
= self.send(local_assigns[:with_select], item, position)
|
26
|
+
|
27
|
+
- if local_assigns[:with_index]
|
28
|
+
%td
|
29
|
+
= position
|
30
|
+
|
31
|
+
- custom_table_fields_totals(fields: fields, item: item, totals: local_assigns[:totals], variant: variant, fields_totals: fields_totals)
|
32
|
+
|
33
|
+
- fields.each do |field, defs|
|
34
|
+
- next if defs[:table] == false
|
35
|
+
- td_classes = [field.to_s]
|
36
|
+
- td_classes += ["text-end"] if defs[:amount]
|
37
|
+
- td_classes += ["text-nowrap"] if defs[:nowrap]
|
38
|
+
- td_classes += ["amount"] if defs[:amount]
|
39
|
+
|
40
|
+
%td{class: td_classes, id: dom_id(item, field)}
|
41
|
+
- v = field_value_for(item, field, definitions: defs, variant: variant)
|
42
|
+
|
43
|
+
- if defs[:editable]
|
44
|
+
|
45
|
+
= editable item, field do
|
46
|
+
- if defs[:link_to_show] == true && custom_table_has_show_route?(item) && can?(:show, item)
|
47
|
+
-# = link_to v, url_for(controller: controller_name, action: "show", id: item.to_param)
|
48
|
+
= link_to v, [namespace, item], data: {turbo: false}
|
49
|
+
- else
|
50
|
+
= v
|
51
|
+
- else
|
52
|
+
- if defs[:link_to_show] == true && custom_table_has_show_route?(item) && can?(:show, item)
|
53
|
+
-# = link_to v, url_for(controller: controller_name, action: "show", id: item.to_param)
|
54
|
+
= link_to v, [namespace, item], data: {turbo: false}
|
55
|
+
- else
|
56
|
+
= v
|
57
|
+
|
58
|
+
- if !local_assigns[:skip_actions]
|
59
|
+
|
60
|
+
%td.text-end.actions
|
61
|
+
- if !local_assigns[:actions].nil?
|
62
|
+
= self.send(local_assigns[:actions], item)
|
63
|
+
- elsif !variant.nil? && self.class.method_defined?("#{variant}_#{model_name}_custom_table_actions")
|
64
|
+
= self.send("#{variant}_#{model_name}_custom_table_actions", item)
|
65
|
+
- elsif self.class.method_defined?("#{model_name}_custom_table_actions")
|
66
|
+
= self.send("#{model_name}_custom_table_actions", item)
|
67
|
+
- if local_assigns[:skip_default_actions].nil?
|
68
|
+
- if (!custom_table_has_show_route?(item) || local_assigns[:force_edit_button]) && can?(:update, item)
|
69
|
+
= custom_table_edit_button [:edit, namespace, local_assigns[:parent], item], id: "edit_#{item.model_name.singular}_#{item.id}", modal: local_assigns[:modal_edit]
|
70
|
+
- if can? :destroy, item
|
71
|
+
- if (Rails.application.routes.recognize_path(url_for([namespace, local_assigns[:parent], item]), :method => :delete) rescue false)
|
72
|
+
= custom_table_delete_button [namespace, local_assigns[:parent], item], id: "destroy_#{item.model_name.singular}_#{item.id}"
|
@@ -0,0 +1,26 @@
|
|
1
|
+
- model_class = item.class
|
2
|
+
- fields = custom_table_fields_for(model_class, use_all_fields: true, variant: local_assigns[:variant], predefined_fields: local_assigns[:fields])
|
3
|
+
- model_name = item.model_name.singular # Allows to show different class models in one table!
|
4
|
+
|
5
|
+
- fields.each do |field, defs|
|
6
|
+
- next if defs[:table] == false
|
7
|
+
|
8
|
+
= turbo_stream.update dom_id(item, field) do
|
9
|
+
- v = field_value_for(item, field, definitions: defs)
|
10
|
+
|
11
|
+
- if defs[:link_to_show] == true && custom_table_has_show_route?(item)
|
12
|
+
-# = link_to v, url_for(controller: controller_name, action: "show", id: item.to_param)
|
13
|
+
= link_to v, [namespace, item]
|
14
|
+
- else
|
15
|
+
= v
|
16
|
+
|
17
|
+
-# %td.text-end.actions
|
18
|
+
-# - if !local_assigns[:actions].nil?
|
19
|
+
-# = self.send(local_assigns[:actions], item)
|
20
|
+
-# - elsif self.class.method_defined?("#{model_name}_custom_table_actions")
|
21
|
+
-# = self.send("#{model_name}_custom_table_actions", item)
|
22
|
+
-# - if local_assigns[:skip_default_actions].nil?
|
23
|
+
-# - if (!has_show_route?(item) || local_assigns[:force_edit_button]) && can?(:update, item)
|
24
|
+
-# = edit_button [:edit, namespace, local_assigns[:parent], item], id: "edit_#{item.model_name.singular}_#{item.id}"
|
25
|
+
-# - if can? :destroy, item
|
26
|
+
-# = delete_button [namespace, local_assigns[:parent], item], id: "destroy_#{item.model_name.singular}_#{item.id}", data: turbo_frame_request? ? {} : {}
|