From d7a0936dd7a874fed09a5f02064ebe29b16a7101 Mon Sep 17 00:00:00 2001 From: James Mason Date: Fri, 21 Sep 2018 17:32:41 -0700 Subject: [PATCH] Convert admin/registrations datatable to AJAX-backed Supercedes https://github.com/openSUSE/osem/pull/2031 . Note: * "Questions" modals have been dropped from this view; questions are no longer asked on registration, since Surveys(PR#1100) were added. --- app/assets/javascripts/osem-datatables.js | 15 ++ .../admin/registrations_controller.rb | 7 + app/datatables/registration_datatable.rb | 56 +++++++ app/views/admin/registrations/index.html.haml | 152 ++++++++++-------- 4 files changed, 167 insertions(+), 63 deletions(-) create mode 100644 app/datatables/registration_datatable.rb diff --git a/app/assets/javascripts/osem-datatables.js b/app/assets/javascripts/osem-datatables.js index 0248275f..f9bdb008 100644 --- a/app/assets/javascripts/osem-datatables.js +++ b/app/assets/javascripts/osem-datatables.js @@ -30,3 +30,18 @@ $(function () { }); }); }); + +function truncatify(selector) { + $(selector).each(function(){ + var text = $(this).text() + $(this).html('' + text + ' ') + }); +} + +function iconize(selector, value, icon, title) { + $(selector).each(function(){ + if ($(this).text() == value) { + $(this).html(""); + } + }); +} diff --git a/app/controllers/admin/registrations_controller.rb b/app/controllers/admin/registrations_controller.rb index fb427d25..3f19ed39 100644 --- a/app/controllers/admin/registrations_controller.rb +++ b/app/controllers/admin/registrations_controller.rb @@ -15,6 +15,13 @@ module Admin @registration_distribution = @conference.registration_distribution @affiliation_distribution = @conference.affiliation_distribution @code_of_conduct = @conference.code_of_conduct.present? + + respond_to do |format| + format.html + format.json do + render json: RegistrationDatatable.new(view_context, conference: @conference) + end + end end def edit; end diff --git a/app/datatables/registration_datatable.rb b/app/datatables/registration_datatable.rb new file mode 100644 index 00000000..bdd97e72 --- /dev/null +++ b/app/datatables/registration_datatable.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +class RegistrationDatatable < AjaxDatatablesRails::Base + def_delegator :@view, :edit_admin_conference_registration_path + + def view_columns + @view_columns ||= { + id: { source: 'Registration.id', cond: :eq }, + name: { source: 'User.name' }, + roles: { source: 'Role.name' }, + email: { source: 'User.email' }, + accepted_code_of_conduct: { source: 'Registration.accepted_code_of_conduct', searchable: false }, + arrival: { source: 'Registration.arrival', searchable: false }, + departure: { source: 'Registration.departure', searchable: false }, + actions: { source: 'Registration.id', searchable: false, orderable: false } + } + end + + private + + def conference + @conference ||= options[:conference] + end + + def conference_role_titles(record) + record.roles.collect do |role| + role.name.titleize if role.resource == conference + end.compact + end + + def data + records.map do |record| + { + id: record.id, + name: record.user.name, + roles: conference_role_titles(record.user), + email: record.email, + accepted_code_of_conduct: !!record.accepted_code_of_conduct, # rubocop:disable Style/DoubleNegation + arrival: record.arrival&.utc, + departure: record.departure&.utc, + questions: {}, + edit_url: edit_admin_conference_registration_path(conference, record), + DT_RowId: record.id + } + end + end + + def get_raw_records # rubocop:disable Naming/AccessorMethodName + conference.registrations.includes(user: :roles).references(:users, :roles).distinct + end + + # override upstream santitation, which converts everything to strings + def sanitize(records) + records + end +end diff --git a/app/views/admin/registrations/index.html.haml b/app/views/admin/registrations/index.html.haml index 212763ca..699d5a9f 100644 --- a/app/views/admin/registrations/index.html.haml +++ b/app/views/admin/registrations/index.html.haml @@ -21,70 +21,96 @@ .row .col-md-12 %div.margin-event-table - %table.datatable#registrations + %table.datatable#registrations{ data: { source: admin_conference_registrations_path(conference_id: @conference, format: :json) } } %thead %tr - %th ID# - %th Name - %th E-Mail - - if @code_of_conduct - %th - %abbr{ title: 'Code of Conduct' } CoC - %th Arrival - %th Departure - - if @conference.questions.any? - %th Questions - %th Actions + %th{ width: '0' } ID# + %th{ width: '25%' } Name + %th{ width: '0' } Roles + %th{ width: '0' } E-Mail + %th{ width: '0' } + %abbr{ title: 'Code of Conduct' } CoC + %th{ width: '0' } Arrival + %th{ width: '0' } Departure + %th{ width: '0' } Actions %tbody - - @registrations.each_with_index do |registration, index| - %tr - %td - = registration.id - %td - = registration.name.present? ? registration.name : registration.username - %br - - registration.user.roles.where(resource: @conference).each do |role| - %span.label.label-info - = role.name.titleize - %td - = registration.email - - if @code_of_conduct - - if registration.accepted_code_of_conduct - %td.text-success.text-center= fa_icon('check', title: 'accepted') - - else - %td.text-center.text-warning - = fa_icon('exclamation-circle', - title: 'Has not accepted Code of Conduct') - %td - - if registration.arrival - = registration.arrival.strftime('%d %b %H:%M') - - else - n/a - %td - - if registration.departure - = registration.departure.strftime('%d %b %H:%M') - - else - n/a - -if @conference.questions.any? - %td - = link_to 'Questions','#', class: 'btn btn-success question-btn', 'data-id' => index, 'data-name' => registration.name - %td{ 'data-order' => registration.attended.to_s } - = check_box_tag "#{@conference.short_title}_#{registration.id}", registration.id, registration.attended, - class: 'switch-checkbox', - url: toggle_attendance_admin_conference_registration_path(@conference.short_title, id: registration.id)+"?attended=" - .btn-group - = link_to 'Edit', edit_admin_conference_registration_path(@conference.short_title, id: registration), - method: :get, class: 'btn btn-primary' - = link_to 'Delete', admin_conference_registration_path(@conference.short_title, registration), - method: :delete, class: 'btn btn-danger', data: { confirm: "Do you really want to delete the Registration for #{registration.name}?" } - - @registrations.each_with_index do |registration, index| - .questions{class: "question#{index}", style: 'display:none;'} - = render partial: 'questions', locals: { registration: registration } -.modal.fade{ id: 'questions', 'role' => 'dialog', 'aria-hidden' => 'true' } - .modal-dialog - .modal-content - .modal-header - %h3{id: 'question-modal-header'} - Questions for Foobar - .modal-body#question-modal-body +:javascript + $(function () { + var codeOfConductPresent = #{@code_of_conduct ? 'true' : 'false'}; + var registrationsDataTable = $('#registrations.datatable').DataTable({ + "processing": true, + "serverSide": true, + "ajax": $('#registrations.datatable').data('source'), + "drawCallback": function(settings) { + checkboxSwitch("[class='switch-checkbox']"); + if (codeOfConductPresent) { + iconize("td.code-of-conduct", "true", "check", "accepted"); + iconize("td.code-of-conduct", "false", "exclamation-circle", "Has not accepted Code of Conduct"); + }; + // truncatify("td.truncate"); + }, + "columns": [ + { + "data": "id" + }, + { + "data": "name", + "className": "truncate", + "render": function(data, type, row) { + var content = '' + data + '
'; + $.each(row.roles, function(index, role){ + content += ' ' + role + '' + }); + return content; + } + }, + { + "name": "roles", + "data": "roles", + "className": "truncate", + "render": function(data, type, row) { + return data.join(', '); + } + }, + { + "data": "email" + }, + { + "data": "accepted_code_of_conduct", + "className": "code-of-conduct text-center", + "searchable": false + }, + { + "data": "arrival", + "searchable": false, + "render": function(data, type, row) { + if (data) { return moment(data).format('ll LT'); } + return ''; + } + }, + { + "data": "departure", + "searchable": false, + "render": function(data, type, row) { + if (data) { return moment(data).format('ll LT'); } + return ''; + } + }, + { + "data": null, + "className": "actions", + "searchable": false, + "sortable": false, + "render": function (data, type, row, meta) { + return '
'+ + 'Edit'+ + '
'; + } + } + ] + }); + + registrationsDataTable.columns(3).visible(codeOfConductPresent); + registrationsDataTable.columns(2).visible(false); + });