Skip to content

Commit 7364223

Browse files
committed
feat: Use interactive table on school questionnaires list
1 parent 449f88f commit 7364223

File tree

7 files changed

+143
-110
lines changed

7 files changed

+143
-110
lines changed

app/assets/javascripts/manage/lib/datatables.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,51 @@
11
// Global settings and initializer
22

3+
function lowercaseFirstChar(string) {
4+
return string.charAt(0).toLowerCase() + string.slice(1);
5+
}
6+
7+
function convertDataAttrsToConfig(target) {
8+
var allData = $(target).data();
9+
var data = Object.keys(allData)
10+
.filter(function(key) {
11+
return key.startsWith('table');
12+
})
13+
.reduce(function(data, rawKey) {
14+
var key = lowercaseFirstChar(rawKey.replace('table', ''));
15+
var value = allData[rawKey];
16+
if (value == 'true' || value == 'false') {
17+
value = value == 'true';
18+
}
19+
data[key] = value;
20+
21+
return data;
22+
}, {});
23+
return data;
24+
}
25+
26+
$.fn.autoDatatable = function() {
27+
var columns = [];
28+
$(this)
29+
.find('thead th')
30+
.each(function() {
31+
var data = convertDataAttrsToConfig(this);
32+
columns.push(data);
33+
});
34+
35+
var config = convertDataAttrsToConfig(this);
36+
if (config.order) {
37+
var parts = config.order.split(' ');
38+
var index = parseInt(parts[0], 10);
39+
var direction = parts.length > 1 ? parts[1] : 'asc';
40+
config.order = [index, direction];
41+
} else {
42+
config.order = [1, 'asc'];
43+
}
44+
config.columns = columns;
45+
46+
window.activeDatatable = $(this).DataTable(config);
47+
};
48+
349
function setupFooterSearch(table) {
450
table.columns().every(function() {
551
var column = this;
@@ -78,6 +124,7 @@ $(document).on('preInit.dt', function(e, settings) {
78124

79125
// init on turbolinks load
80126
$(document).on('turbolinks:load', function() {
127+
$('table[data-auto-datatable]').autoDatatable();
81128
if (!$.fn.DataTable.isDataTable('table[id^=dttb-]')) {
82129
$('table[id^=dttb-]').DataTable();
83130
}

app/assets/javascripts/manage/lib/jquery.bulkRowedit.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ $.fn.bulkRowEdit = function() {
4141
},
4242
})
4343
.done(function() {
44-
window.questionnairesDataTable.draw(false);
44+
window.activeDatatable.draw(false);
4545
})
4646
.fail(function() {
4747
alert('Request failed, please refresh the page or try again later.');

app/assets/javascripts/manage/lib/setupDataTables.js

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,10 @@
1-
var setupDataTables = function() {
2-
window.questionnairesDataTable = $('.datatable.questionnaires').DataTable({
3-
order: [3, 'desc'],
4-
columns: [
5-
{ orderable: false, data: 'bulk' },
6-
{ orderable: false, data: 'link' },
7-
{ orderable: false, data: 'note' },
8-
{ orderable: true, data: 'id', visible: false },
9-
{ orderable: true, data: 'first_name' },
10-
{ orderable: true, data: 'last_name' },
11-
{ orderable: true, data: 'email', visible: false },
12-
{ orderable: true, data: 'phone', visible: false },
13-
{ orderable: true, data: 'gender', visible: false },
14-
{ orderable: true, data: 'date_of_birth', visible: false },
15-
{ orderable: true, data: 'acc_status' },
16-
{ orderable: true, data: 'checked_in' },
17-
{ orderable: true, data: 'school' },
18-
{ orderable: true, data: 'created_at' },
19-
{ orderable: true, data: 'dietary_restrictions', visible: false },
20-
{ orderable: true, data: 'special_needs', visible: false },
21-
],
22-
});
1+
/*
2+
* NOTE: This should only be used for legacy datatables.
3+
* All future datatables should be generated using data-table-* HTML attributes.
4+
* See app/views/manage/application/_questionnaire_datatable.html.haml for an example.
5+
*/
236

7+
var setupDataTables = function() {
248
$('.datatable.checkins').DataTable({
259
order: [1, 'asc'],
2610
columns: [

app/datatables/questionnaire_datatable.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ def view_columns
1313
role: { source: "User.role", cond: :eq, searchable: false },
1414
acc_status: { source: "Questionnaire.acc_status", searchable: true },
1515
checked_in: { source: "Questionnaire.checked_in_at", searchable: false },
16+
boarded_bus: { source: "Questionnaire.boarded_bus_at", searchable: false },
1617
school: { source: "School.name" },
1718
created_at: { source: "Questionnaire.created_at", searchable: false },
1819
dietary_restrictions: { source: "Questionnaire.dietary_restrictions", searchable: true },
@@ -45,7 +46,8 @@ def data
4546
gender: record.gender,
4647
date_of_birth: record.date_of_birth_formatted,
4748
acc_status: "<span class=\"text-#{acc_status_class(record.acc_status)}\">#{record.acc_status.titleize}</span>".html_safe,
48-
checked_in: record.checked_in? ? '<span class="text-success">Yes</span>'.html_safe : "No",
49+
checked_in: record.checked_in? ? '<span class="badge badge-success">Yes</span>'.html_safe : "No",
50+
boarded_bus: record.boarded_bus? ? '<span class="badge badge-success">Yes</span>'.html_safe : "No",
4951
school: link_to(record.school.name, manage_school_path(record.school)),
5052
created_at: record.created_at.present? ? display_datetime(record.created_at) : "",
5153
dietary_restrictions: record.dietary_restrictions,
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
:ruby
2+
params = { format: :json }
3+
if defined?(scope_params)
4+
params = params.merge(scope_params)
5+
end
6+
data_source = datatable_manage_questionnaires_path(params)
7+
8+
columns ||= %w(link note first_name last_name email acc_status checked_in school created_at)
9+
visible = -> (column, columns) { columns.include?(column) ? 'true' : 'false' }
10+
11+
# Use default page length if not defined
12+
page_length ||= nil
13+
14+
%div
15+
%table.datatable.table.table-striped.table-hover{ data: { "auto-datatable": true, source: data_source, "table-order": "14 desc", 'page-length': page_length } }
16+
%thead
17+
%tr
18+
%th{'data-table': { orderable: 'false', data: 'bulk' }}
19+
- if current_user.admin?
20+
%input{ type: "checkbox", name: "select_allc", value: "1", data: { bulk_row_select: "" } }
21+
%th{'data-table': { orderable: 'false', data: 'link', visible: visible.call('link', columns) }}
22+
%th{'data-table': { orderable: 'false', data: 'note', visible: visible.call('note', columns) }}
23+
%th{'data-table': { orderable: 'true', data: 'id', visible: visible.call('id', columns) }} ID
24+
%th{'data-table': { orderable: 'true', data: 'first_name', visible: visible.call('first_name', columns) }} First name
25+
%th{'data-table': { orderable: 'true', data: 'last_name', visible: visible.call('last_name', columns) }} Last name
26+
%th{'data-table': { orderable: 'true', data: 'email', visible: visible.call('email', columns) }} Email
27+
%th{'data-table': { orderable: 'true', data: 'phone', visible: visible.call('phone', columns) }} Phone
28+
%th{'data-table': { orderable: 'true', data: 'gender', visible: visible.call('gender', columns) }} Gender
29+
%th{'data-table': { orderable: 'true', data: 'date_of_birth', visible: visible.call('date_of_birth', columns) }} Date of birth
30+
%th{'data-table': { orderable: 'true', data: 'acc_status', visible: visible.call('acc_status', columns) }} Status
31+
%th{'data-table': { orderable: 'true', data: 'checked_in', visible: visible.call('checked_in', columns) }} Checked in
32+
%th{'data-table': { orderable: 'true', data: 'boarded_bus', visible: visible.call('boarded_bus', columns) }} Boarded bus
33+
%th{'data-table': { orderable: 'true', data: 'school', visible: visible.call('school', columns) }} School
34+
%th{'data-table': { orderable: 'true', data: 'created_at', visible: visible.call('created_at', columns) }} Applied on
35+
%th{'data-table': { orderable: 'true', data: 'dietary_restrictions', visible: visible.call('dietary_restrictions', columns) }} Dietary restrictions
36+
%th{'data-table': { orderable: 'true', data: 'special_needs', visible: visible.call('special_needs', columns) }} Special needs
37+
%tbody
38+
%tfoot
39+
%tr
40+
%th
41+
%th
42+
%th
43+
%th
44+
%input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'ID'}
45+
%th
46+
%input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'First name'}
47+
%th
48+
%input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'Last name'}
49+
%th
50+
%input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'Email'}
51+
%th
52+
%input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'Phone'}
53+
%th
54+
%input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'Gender'}
55+
%th
56+
%th
57+
%select.form-control.form-control-sm
58+
%option{value: ''} Status
59+
- Questionnaire::POSSIBLE_ACC_STATUS.each do |key, value|
60+
%option{value: key}= value
61+
%th
62+
%th
63+
%th
64+
%input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'School'}
65+
%th
66+
%th
67+
%input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'Dietary restrictions'}
68+
%th
69+
%input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'Special needs'}
70+
71+
72+
.row
73+
.col-sm-7.col-lg-6
74+
%br
75+
.card
76+
.card-body
77+
%h5.card-title Bulk Action
78+
= bs_vertical_simple_form Questionnaire.new, url: bulk_apply_manage_questionnaires_path, html: { data: { bulk_row_edit: true } } do |f|
79+
= f.input :acc_status, as: :select, collection: Questionnaire::POSSIBLE_ACC_STATUS.invert, include_blank: false, label: "Acceptance Status:", input_html: { data: { bulk_row_edit: true } }, hint: "Updating this status may trigger an automatic email to each applicant - see below for details."
80+
= f.button :submit, value: "Update Status", data: { bulk_row_edit: true }, class: 'btn-primary'
Lines changed: 3 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,11 @@
11
= render "layouts/manage/page_title", title: "Questionnaires" do
22
= link_to "New Questionnaire", new_manage_questionnaire_path, class: "btn btn-sm btn-outline-secondary"
33

4-
%div
5-
%table.questionnaires.datatable.table.table-striped.table-hover{ "data-source" => datatable_manage_questionnaires_path(format: :json) }
6-
%thead
7-
%tr
8-
%th
9-
- if current_user.admin?
10-
%input{ type: "checkbox", name: "select_allc", value: "1", data: { bulk_row_select: "" } }
11-
%th
12-
%th
13-
%th ID
14-
%th First name
15-
%th Last name
16-
%th Email
17-
%th Phone
18-
%th Gender
19-
%th Date of birth
20-
%th Status
21-
%th Checked In
22-
%th School
23-
%th Applied on
24-
%th Dietary restrictions
25-
%th Special needs
26-
%tbody
27-
%tfoot
28-
%tr
29-
%th
30-
%th
31-
%th
32-
%th
33-
%input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'ID'}
34-
%th
35-
%input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'First name'}
36-
%th
37-
%input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'Last name'}
38-
%th
39-
%input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'Email'}
40-
%th
41-
%input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'Phone'}
42-
%th
43-
%input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'Gender'}
44-
%th
45-
%th
46-
%select.form-control.form-control-sm
47-
%option{value: ''} Status
48-
- Questionnaire::POSSIBLE_ACC_STATUS.each do |key, value|
49-
%option{value: key}= value
50-
%th
51-
%th
52-
%input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'School'}
53-
%th
54-
%th
55-
%input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'Dietary restrictions'}
56-
%th
57-
%input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'Special needs'}
4+
= render "questionnaire_datatable"
585

6+
%hr
597

60-
.row
61-
.col-sm-7.col-lg-6
62-
%br
63-
.card
64-
.card-body
65-
%h5.card-title Bulk Action
66-
= bs_vertical_simple_form Questionnaire.new, url: bulk_apply_manage_questionnaires_path, html: { data: { bulk_row_edit: true } } do |f|
67-
= f.input :acc_status, as: :select, collection: Questionnaire::POSSIBLE_ACC_STATUS.invert, include_blank: false, label: "Acceptance Status:", input_html: { data: { bulk_row_edit: true } }, hint: "Updating this status may trigger an automatic email to each applicant - see below for details."
68-
= f.button :submit, value: "Update Status", data: { bulk_row_edit: true }, class: 'btn-primary'
69-
70-
%hr
71-
72-
= render 'triggered_email_summary'
8+
= render 'triggered_email_summary'
739

7410
.mb-4
7511
= render 'docs_link', title: 'Questionnaire documentation', url: 'https://coderit.org/hackathon-manager/docs/questionnaires'

app/views/manage/schools/show.html.haml

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -77,27 +77,11 @@
7777

7878
.row.mt-2
7979
.col
80-
%h4.pb-0
80+
%h4.border-bottom.pb-2.mb-3
8181
Questionnaires
8282
%small.text-muted (#{@school.questionnaires.count} total, #{@school.questionnaires.count { |q| q.checked_in? }} checked in)
83-
%table.table
84-
%thead
85-
%tr
86-
%th
87-
%th First Name
88-
%th Last Name
89-
%th Email
90-
%th Status
91-
%th Checked In?
92-
%tbody
93-
- @school.questionnaires.order(:acc_status).each do |q|
94-
%tr
95-
%td= link_to '<i class="fa fa-search"></i>'.html_safe, manage_questionnaire_path(q)
96-
%td= q.first_name
97-
%td= q.last_name
98-
%td= q.email
99-
%td= "<span class=\"text-#{acc_status_class(q.acc_status)}\">#{Questionnaire::POSSIBLE_ACC_STATUS[q.acc_status]}</span>".html_safe
100-
%td= q.checked_in? ? "Yes" : "No"
83+
84+
= render "questionnaire_datatable", scope_params: { school_id: @school.id }, page_length: 25, columns: %w(link note first_name last_name email acc_status checked_in created_at)
10185

10286
.row.mt-2.mb-4
10387
.col-lg-6

0 commit comments

Comments
 (0)