diff --git a/CHANGELOG.md b/CHANGELOG.md index c040ae238..f7db07a66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,21 @@ +# [1.7.0](https://github.com/codeRIT/hackathon-manager/compare/v1.6.0...v1.7.0) (2019-05-29) + + +### Features + +* Add ability to mark a school as a home school ([86cad60](https://github.com/codeRIT/hackathon-manager/commit/86cad60)), closes [#157](https://github.com/codeRIT/hackathon-manager/issues/157) +* Always show interested bus captains table ([e0142d9](https://github.com/codeRIT/hackathon-manager/commit/e0142d9)) +* Rename RIT/non-RIT to Home/Away ([3d1d1c1](https://github.com/codeRIT/hackathon-manager/commit/3d1d1c1)), closes [#157](https://github.com/codeRIT/hackathon-manager/issues/157) +* Use interactive table on bus list passengers ([90f3b7b](https://github.com/codeRIT/hackathon-manager/commit/90f3b7b)) +* Use interactive table on school questionnaires list ([7364223](https://github.com/codeRIT/hackathon-manager/commit/7364223)) + + +### Maintenance + +* Remove unused coffeescript gem ([556ac98](https://github.com/codeRIT/hackathon-manager/commit/556ac98)) +* Update gems ([342dce7](https://github.com/codeRIT/hackathon-manager/commit/342dce7)) +* Upgrade to ajax-datatables-rails 1.x ([3c2d6d3](https://github.com/codeRIT/hackathon-manager/commit/3c2d6d3)) + # [1.6.0](https://github.com/codeRIT/hackathon-manager/compare/v1.5.0...v1.6.0) (2019-05-29) diff --git a/Gemfile b/Gemfile index e671a1216..72f476e3c 100644 --- a/Gemfile +++ b/Gemfile @@ -18,7 +18,7 @@ gem 'uglifier', '>= 1.3.0' # gem 'mini_racer', platforms: :ruby # Use CoffeeScript for .coffee assets and views -gem 'coffee-rails', '~> 4.2' +# gem 'coffee-rails', '~> 4.2' # Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks gem 'turbolinks', '~> 5' # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder @@ -48,9 +48,9 @@ gem "aws-sdk-s3", require: false gem "file_validators" # Templating utilities -gem 'haml-rails', '~> 1.0' +gem 'haml-rails', '~> 2.0' gem 'simple_form' -gem 'ajax-datatables-rails', '~> 0.4.0' # Does NOT follow semver +gem 'ajax-datatables-rails', '~> 1.0' gem 'roadie-rails' gem 'chartkick', '~> 3.0' gem 'groupdate' diff --git a/Gemfile.lock b/Gemfile.lock index 8ace4f5cf..8287095dc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -44,8 +44,8 @@ GEM tzinfo (~> 1.1) addressable (2.6.0) public_suffix (>= 2.0.2, < 4.0) - ajax-datatables-rails (0.4.3) - railties (>= 4.0) + ajax-datatables-rails (1.0.0) + railties (>= 4.2) ansi (1.5.0) archive-zip (0.12.0) io-like (~> 0.3.0) @@ -55,17 +55,17 @@ GEM autoprefixer-rails (9.5.1.1) execjs aws-eventstream (1.0.3) - aws-partitions (1.164.0) - aws-sdk-core (3.52.1) + aws-partitions (1.168.0) + aws-sdk-core (3.54.0) aws-eventstream (~> 1.0, >= 1.0.2) aws-partitions (~> 1.0) aws-sigv4 (~> 1.1) jmespath (~> 1.0) - aws-sdk-kms (1.20.0) - aws-sdk-core (~> 3, >= 3.52.1) + aws-sdk-kms (1.21.0) + aws-sdk-core (~> 3, >= 3.53.0) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.39.0) - aws-sdk-core (~> 3, >= 3.52.1) + aws-sdk-s3 (1.40.0) + aws-sdk-core (~> 3, >= 3.53.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.0) aws-sigv4 (1.1.0) @@ -78,7 +78,7 @@ GEM bindex (0.7.0) binding_of_caller (0.8.0) debug_inspector (>= 0.0.1) - blazer (2.0.1) + blazer (2.0.2) activerecord (>= 4.2) chartkick railties (>= 4.2) @@ -91,15 +91,15 @@ GEM sassc-rails (>= 2.0.0) builder (3.2.3) byebug (11.0.1) - capybara (3.20.2) + capybara (3.21.0) addressable mini_mime (>= 0.1.3) nokogiri (~> 1.8) rack (>= 1.6.0) rack-test (>= 0.6.3) - regexp_parser (~> 1.2) + regexp_parser (~> 1.5) xpath (~> 3.2) - chartkick (3.0.2) + chartkick (3.1.0) childprocess (1.0.1) rake (< 13.0) chromedriver-helper (2.1.1) @@ -108,13 +108,6 @@ GEM codeclimate-test-reporter (0.6.0) simplecov (>= 0.7.1, < 1.0.0) coderay (1.1.2) - coffee-rails (4.2.2) - coffee-script (>= 2.2.0) - railties (>= 4.0.0) - coffee-script (2.4.1) - coffee-script-source - execjs - coffee-script-source (1.12.2) concurrent-ruby (1.1.5) connection_pool (2.2.2) crack (0.4.3) @@ -166,7 +159,7 @@ GEM raabro (~> 1.1) globalid (0.4.2) activesupport (>= 4.2.0) - groupdate (4.1.1) + groupdate (4.1.2) activesupport (>= 4.2) guard (2.15.0) formatador (>= 0.2.4) @@ -181,16 +174,16 @@ GEM guard-minitest (2.4.6) guard-compat (~> 1.2) minitest (>= 3.0) - haml (5.1.0) + haml (5.1.1) temple (>= 0.8.0) tilt - haml-rails (1.0.0) - actionpack (>= 4.0.1) - activesupport (>= 4.0.1) + haml-rails (2.0.1) + actionpack (>= 5.1) + activesupport (>= 5.1) haml (>= 4.0.6, < 6.0) html2haml (>= 1.0.1) - railties (>= 4.0.1) - hashdiff (0.3.9) + railties (>= 5.1) + hashdiff (0.4.0) hashie (3.6.0) highcharts-rails (6.0.3) railties (>= 3.1) @@ -218,7 +211,7 @@ GEM jquery-ui-rails (= 4.0.3) railties (>= 3.1.0) json (2.2.0) - jwt (2.1.0) + jwt (2.2.1) listen (3.1.5) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) @@ -279,7 +272,7 @@ GEM pry (0.12.2) coderay (~> 1.1.0) method_source (~> 0.9.0) - public_suffix (3.0.3) + public_suffix (3.1.0) puma (3.12.1) raabro (1.1.6) rack (2.0.7) @@ -328,7 +321,7 @@ GEM ffi (~> 1.0) redcarpet (3.4.0) redis (4.1.1) - regexp_parser (1.5.0) + regexp_parser (1.5.1) responders (2.4.1) actionpack (>= 4.2.0, < 6.0) railties (>= 4.2.0, < 6.0) @@ -338,13 +331,13 @@ GEM roadie-rails (2.1.0) railties (>= 5.1, < 6.1) roadie (~> 3.1) - rollbar (2.19.4) + rollbar (2.20.0) multi_json - ruby-progressbar (1.10.0) + ruby-progressbar (1.10.1) ruby_dep (1.5.0) ruby_parser (3.13.1) sexp_processor (~> 4.9) - rubyzip (1.2.2) + rubyzip (1.2.3) safe_yaml (1.0.5) safely_block (0.2.1) errbase @@ -369,7 +362,7 @@ GEM sprockets-rails tilt selectize-rails (0.12.6) - selenium-webdriver (3.142.2) + selenium-webdriver (3.142.3) childprocess (>= 0.5, < 2.0) rubyzip (~> 1.2, >= 1.2.2) sexp_processor (4.12.0) @@ -399,9 +392,9 @@ GEM json (>= 1.8, < 3) simplecov-html (~> 0.10.0) simplecov-html (0.10.2) - skylight (4.0.1) - skylight-core (= 4.0.1) - skylight-core (4.0.1) + skylight (4.0.2) + skylight-core (= 4.0.2) + skylight-core (4.0.2) activesupport (>= 4.2.0) sparkpost_rails (1.5.1) rails (>= 4.0, < 5.3) @@ -458,7 +451,7 @@ PLATFORMS ruby DEPENDENCIES - ajax-datatables-rails (~> 0.4.0) + ajax-datatables-rails (~> 1.0) audited (~> 4.7) aws-sdk-s3 better_errors @@ -471,7 +464,6 @@ DEPENDENCIES chartkick (~> 3.0) chromedriver-helper codeclimate-test-reporter (~> 0.6.0) - coffee-rails (~> 4.2) devise (~> 4.2) devise-doorkeeper doorkeeper (~> 5.0) @@ -482,7 +474,7 @@ DEPENDENCIES groupdate guard guard-minitest - haml-rails (~> 1.0) + haml-rails (~> 2.0) highcharts-rails (~> 6.0) httparty jquery-rails diff --git a/app/assets/javascripts/manage/lib/datatables.js b/app/assets/javascripts/manage/lib/datatables.js index c2eef7d83..a609d6c6a 100644 --- a/app/assets/javascripts/manage/lib/datatables.js +++ b/app/assets/javascripts/manage/lib/datatables.js @@ -1,5 +1,56 @@ // Global settings and initializer +function lowercaseFirstChar(string) { + return string.charAt(0).toLowerCase() + string.slice(1); +} + +function convertDataAttrsToConfig(target) { + var allData = $(target).data(); + var data = Object.keys(allData) + .filter(function(key) { + return key.startsWith('table'); + }) + .reduce(function(data, rawKey) { + var key = lowercaseFirstChar(rawKey.replace('table', '')); + var value = allData[rawKey]; + if (value == 'true' || value == 'false') { + value = value == 'true'; + } + data[key] = value; + + return data; + }, {}); + return data; +} + +$.fn.autoDatatable = function() { + var columns = []; + $(this) + .find('thead th') + .each(function() { + var data = convertDataAttrsToConfig(this); + columns.push(data); + }); + + var config = convertDataAttrsToConfig(this); + if (config.order) { + var sequence = config.order.split(',').map(function(piece) { + return piece.trim(); + }); + config.order = sequence.map(function(piece) { + var parts = piece.split(' '); + var index = parseInt(parts[0], 10); + var direction = parts.length > 1 ? parts[1] : 'asc'; + return [index, direction]; + }); + } else { + config.order = [1, 'asc']; + } + config.columns = columns; + + window.activeDatatable = $(this).DataTable(config); +}; + function setupFooterSearch(table) { table.columns().every(function() { var column = this; @@ -78,6 +129,7 @@ $(document).on('preInit.dt', function(e, settings) { // init on turbolinks load $(document).on('turbolinks:load', function() { + $('table[data-auto-datatable]').autoDatatable(); if (!$.fn.DataTable.isDataTable('table[id^=dttb-]')) { $('table[id^=dttb-]').DataTable(); } diff --git a/app/assets/javascripts/manage/lib/jquery.bulkRowedit.js b/app/assets/javascripts/manage/lib/jquery.bulkRowedit.js index 64776d894..2ca2499ed 100644 --- a/app/assets/javascripts/manage/lib/jquery.bulkRowedit.js +++ b/app/assets/javascripts/manage/lib/jquery.bulkRowedit.js @@ -41,7 +41,7 @@ $.fn.bulkRowEdit = function() { }, }) .done(function() { - window.questionnairesDataTable.draw(false); + window.activeDatatable.draw(false); }) .fail(function() { alert('Request failed, please refresh the page or try again later.'); diff --git a/app/assets/javascripts/manage/lib/setupDataTables.js b/app/assets/javascripts/manage/lib/setupDataTables.js index 30eee80c1..ec5c53297 100644 --- a/app/assets/javascripts/manage/lib/setupDataTables.js +++ b/app/assets/javascripts/manage/lib/setupDataTables.js @@ -1,26 +1,10 @@ -var setupDataTables = function() { - window.questionnairesDataTable = $('.datatable.questionnaires').DataTable({ - order: [3, 'desc'], - columns: [ - { orderable: false, data: 'bulk' }, - { orderable: false, data: 'link' }, - { orderable: false, data: 'note' }, - { orderable: true, data: 'id', visible: false }, - { orderable: true, data: 'first_name' }, - { orderable: true, data: 'last_name' }, - { orderable: true, data: 'email', visible: false }, - { orderable: true, data: 'phone', visible: false }, - { orderable: true, data: 'gender', visible: false }, - { orderable: true, data: 'date_of_birth', visible: false }, - { orderable: true, data: 'acc_status' }, - { orderable: true, data: 'checked_in' }, - { orderable: true, data: 'school' }, - { orderable: true, data: 'created_at' }, - { orderable: true, data: 'dietary_restrictions', visible: false }, - { orderable: true, data: 'special_needs', visible: false }, - ], - }); +/* + * NOTE: This should only be used for legacy datatables. + * All future datatables should be generated using data-table-* HTML attributes. + * See app/views/manage/application/_questionnaire_datatable.html.haml for an example. + */ +var setupDataTables = function() { $('.datatable.checkins').DataTable({ order: [1, 'asc'], columns: [ @@ -58,13 +42,14 @@ var setupDataTables = function() { }); $('.datatable.schools').DataTable({ - order: [4, 'desc'], + order: [[5, 'desc'], [4, 'desc']], columns: [ { orderable: true, data: 'id', visible: false }, { orderable: true, data: 'name' }, { orderable: true, data: 'city' }, { orderable: true, data: 'state' }, { orderable: true, data: 'questionnaire_count' }, + { orderable: true, data: 'home_school' }, ], }); diff --git a/app/controllers/manage/admins_controller.rb b/app/controllers/manage/admins_controller.rb index be37a03de..f22d6d794 100644 --- a/app/controllers/manage/admins_controller.rb +++ b/app/controllers/manage/admins_controller.rb @@ -8,7 +8,7 @@ def index end def datatable - render json: AdminDatatable.new(view_context) + render json: AdminDatatable.new(params, view_context: view_context) end def show diff --git a/app/controllers/manage/checkins_controller.rb b/app/controllers/manage/checkins_controller.rb index d78547c05..4da494cb8 100644 --- a/app/controllers/manage/checkins_controller.rb +++ b/app/controllers/manage/checkins_controller.rb @@ -8,7 +8,7 @@ def index end def datatable - render json: CheckinDatatable.new(view_context) + render json: CheckinDatatable.new(params, view_context: view_context) end def show diff --git a/app/controllers/manage/dashboard_controller.rb b/app/controllers/manage/dashboard_controller.rb index e73a82baa..6a415b11f 100644 --- a/app/controllers/manage/dashboard_controller.rb +++ b/app/controllers/manage/dashboard_controller.rb @@ -15,7 +15,7 @@ def todays_activity_data if params[:school_id] where_filter = { school_id: params[:school_id] } else - types << "Non-Applied Users" + types << "Incomplete Applications" end render json: activity_chart_data(types, "hour", Time.zone.today.beginning_of_day..Time.zone.today.end_of_day, where_filter) end @@ -26,7 +26,7 @@ def todays_stats_data "Applications" => Questionnaire.where("created_at >= :date_min", date_min: date_min).count, "Confirmations" => Questionnaire.where("acc_status = \"rsvp_confirmed\" AND acc_status_date >= :date_min", date_min: date_min).count, "Denials" => Questionnaire.where("acc_status = \"rsvp_denied\" AND acc_status_date >= :date_min", date_min: date_min).count, - "Non-Applied Users" => User.without_questionnaire.where("users.created_at >= :date_min", date_min: date_min).count + "Incomplete Applications" => User.without_questionnaire.where("users.created_at >= :date_min", date_min: date_min).count, } end @@ -43,16 +43,16 @@ def confirmation_activity_data end def application_activity_data - render json: activity_chart_data(["Non-RIT Applications", "RIT Applications", "Non-Applied Users"], "day", 3.week.ago..Time.zone.now) + render json: activity_chart_data(["Away Applications", "Home Applications", "Incomplete Applications"], "day", 3.week.ago..Time.zone.now) end def user_distribution_data total_stats_data = {} total_count = Questionnaire.count - rit_count = Questionnaire.where("school_id = \"2304\"").count - total_stats_data["Non-Applied Users"] = User.without_questionnaire.count - total_stats_data["Non-RIT Applications"] = total_count - rit_count - total_stats_data["RIT Applications"] = rit_count + rit_count = Questionnaire.joins(:school).where("schools.is_home = true").count + total_stats_data["Incomplete Applications"] = User.without_questionnaire.count + total_stats_data["Away Applications"] = total_count - rit_count + total_stats_data["Home Applications"] = rit_count render json: total_stats_data end @@ -63,8 +63,8 @@ def application_distribution_data end def schools_confirmed_data - schools = Questionnaire.joins(:school).group('schools.name').where("acc_status = 'rsvp_confirmed'").order("schools.name ASC").count - schools_riding = Questionnaire.joins(:school).group('schools.name').where("acc_status = 'rsvp_confirmed' AND bus_list_id").count + schools = Questionnaire.joins(:school).group("schools.name").where("acc_status = 'rsvp_confirmed'").order("schools.name ASC").count + schools_riding = Questionnaire.joins(:school).group("schools.name").where("acc_status = 'rsvp_confirmed' AND bus_list_id").count schools = schools.map do |name, count| bus_count_row = schools_riding.select { |school_bus_name, _| school_bus_name == name } bus_count = bus_count_row ? bus_count_row[name] || 0 : 0 @@ -73,7 +73,7 @@ def schools_confirmed_data end render json: [ { name: "Not riding bus", data: schools.sort_by { |_, no_bus, bus| [bus, no_bus] }.reverse }, - { name: "Riding bus", data: schools_riding } + { name: "Riding bus", data: schools_riding }, ] end @@ -85,7 +85,7 @@ def schools_applied_data "late_waitlist" => {}, "waitlist" => {}, "accepted" => {}, - "rsvp_confirmed" => {} + "rsvp_confirmed" => {}, } # Temporary fix # result = Questionnaire.joins(:school).group(:acc_status, "schools.name").where("schools.questionnaire_count >= 5").order("schools.questionnaire_count DESC").order("schools.name ASC").count @@ -104,7 +104,7 @@ def schools_applied_data { name: "Late Waitlisted", data: counted_schools["late_waitlist"] }, { name: "RSVP Denied", data: counted_schools["rsvp_denied"] }, { name: "Denied", data: counted_schools["denied"] }, - { name: "Pending", data: counted_schools["pending"] } + { name: "Pending", data: counted_schools["pending"] }, ] end @@ -116,22 +116,22 @@ def activity_chart_data(types, group_type, range, where_filter = nil) case type when "Applications" data = Questionnaire.send("group_by_#{group_type}", :created_at, range: range) - when "RIT Applications" - data = Questionnaire.where("school_id = \"2304\"").send("group_by_#{group_type}", :created_at, range: range) - when "Non-RIT Applications" - data = Questionnaire.where("school_id != \"2304\"").send("group_by_#{group_type}", :created_at, range: range) + when "Home Applications" + data = Questionnaire.joins(:school).where("schools.is_home = true").send("group_by_#{group_type}", :created_at, range: range) + when "Away Applications" + data = Questionnaire.joins(:school).where("schools.is_home != true").send("group_by_#{group_type}", :created_at, range: range) when "Confirmations" data = Questionnaire.where(acc_status: "rsvp_confirmed").send("group_by_#{group_type}", :acc_status_date, range: range) when "Denials" data = Questionnaire.where(acc_status: "rsvp_denied").send("group_by_#{group_type}", :acc_status_date, range: range) - when "Non-Applied Users" + when "Incomplete Applications" data = User.without_questionnaire.send("group_by_#{group_type}", "users.created_at", range: range) when "Checked In" data = Questionnaire.where("checked_in_at > 0").send("group_by_#{group_type}", :checked_in_at, range: range) when "Boarded Bus" data = Questionnaire.where("boarded_bus_at > 0").send("group_by_#{group_type}", :boarded_bus_at, range: range) end - data = data.where(where_filter) if where_filter && type != "Non-Applied Users" + data = data.where(where_filter) if where_filter && type != "Incomplete Applications" chart_data << { name: type, data: data.count } end chart_data diff --git a/app/controllers/manage/messages_controller.rb b/app/controllers/manage/messages_controller.rb index 33380188c..245e2b07f 100644 --- a/app/controllers/manage/messages_controller.rb +++ b/app/controllers/manage/messages_controller.rb @@ -10,7 +10,7 @@ def index end def datatable - render json: BulkMessageDatatable.new(view_context) + render json: BulkMessageDatatable.new(params, view_context: view_context) end def show diff --git a/app/controllers/manage/questionnaires_controller.rb b/app/controllers/manage/questionnaires_controller.rb index 3060466a8..70873a9b8 100644 --- a/app/controllers/manage/questionnaires_controller.rb +++ b/app/controllers/manage/questionnaires_controller.rb @@ -10,7 +10,7 @@ def index end def datatable - render json: QuestionnaireDatatable.new(view_context) + render json: QuestionnaireDatatable.new(params, view_context: view_context) end def show @@ -42,7 +42,7 @@ def create if user.errors.include?(:email) @questionnaire.errors.add(:email, user.errors[:email].join(", ")) end - return render 'new' + return render "new" end end respond_with(:manage, @questionnaire) @@ -162,7 +162,7 @@ def questionnaire_params def convert_boarded_bus_param(values, questionnaire = nil) boarded_bus = values.delete(:boarded_bus) current_value = questionnaire&.boarded_bus_at - values[:boarded_bus_at] = boarded_bus == '1' ? (current_value || Time.now) : nil + values[:boarded_bus_at] = boarded_bus == "1" ? (current_value || Time.now) : nil values end diff --git a/app/controllers/manage/schools_controller.rb b/app/controllers/manage/schools_controller.rb index 9cbd3609c..71ebb6785 100644 --- a/app/controllers/manage/schools_controller.rb +++ b/app/controllers/manage/schools_controller.rb @@ -8,7 +8,7 @@ def index end def datatable - render json: SchoolDatatable.new(view_context) + render json: SchoolDatatable.new(params, view_context: view_context) end def show @@ -78,7 +78,7 @@ def perform_merge def school_params params.require(:school).permit( - :name, :address, :city, :state + :name, :address, :city, :state, :is_home ) end diff --git a/app/datatables/admin_datatable.rb b/app/datatables/admin_datatable.rb index f31a7d6d5..7fc90affc 100644 --- a/app/datatables/admin_datatable.rb +++ b/app/datatables/admin_datatable.rb @@ -1,4 +1,4 @@ -class AdminDatatable < AjaxDatatablesRails::Base +class AdminDatatable < ApplicationDatatable def_delegators :@view, :link_to, :manage_admin_path, :bold, :display_datetime def view_columns @@ -27,10 +27,7 @@ def data end end - # rubocop:disable Naming/AccessorMethodName def get_raw_records User.where(role: [:admin, :admin_limited_access, :event_tracking]) end - - # rubocop:enable Naming/AccessorMethodName end diff --git a/app/datatables/application_datatable.rb b/app/datatables/application_datatable.rb new file mode 100644 index 000000000..ded563ac6 --- /dev/null +++ b/app/datatables/application_datatable.rb @@ -0,0 +1,9 @@ +class ApplicationDatatable < AjaxDatatablesRails::ActiveRecord + extend Forwardable + attr_reader :view + + def initialize(params, opts = {}) + @view = opts[:view_context] + super + end +end diff --git a/app/datatables/bulk_message_datatable.rb b/app/datatables/bulk_message_datatable.rb index be760bcd2..ace23f2f5 100644 --- a/app/datatables/bulk_message_datatable.rb +++ b/app/datatables/bulk_message_datatable.rb @@ -1,4 +1,4 @@ -class BulkMessageDatatable < AjaxDatatablesRails::Base +class BulkMessageDatatable < ApplicationDatatable def_delegators :@view, :link_to, :manage_message_path, :display_datetime, :bold, :h def view_columns @@ -8,7 +8,7 @@ def view_columns subject: { source: "Message.subject" }, created_at: { source: "Message.created_at", searchable: false }, updated_at: { source: "Message.updated_at", searchable: false }, - delivered_at: { source: "Message.delivered_at", searchable: false } + delivered_at: { source: "Message.delivered_at", searchable: false }, } end @@ -20,17 +20,15 @@ def data id: record.id, name: link_to(bold(record.name), manage_message_path(record)), subject: record.subject, - status: record.status == 'drafted' ? "#{h(record.status.titleize)}".html_safe : record.status.titleize, + status: record.status == "drafted" ? "#{h(record.status.titleize)}".html_safe : record.status.titleize, created_at: display_datetime(record.created_at), - updated_at: record.updated_at.present? ? display_datetime(record.updated_at) : '', - delivered_at: record.delivered_at.present? ? display_datetime(record.delivered_at) : '' + updated_at: record.updated_at.present? ? display_datetime(record.updated_at) : "", + delivered_at: record.delivered_at.present? ? display_datetime(record.delivered_at) : "", } end end - # rubocop:disable Naming/AccessorMethodName def get_raw_records - Message.where(type: 'bulk') + Message.where(type: "bulk") end - # rubocop:enable Naming/AccessorMethodName end diff --git a/app/datatables/checkin_datatable.rb b/app/datatables/checkin_datatable.rb index 3bdccb816..2d19f0d37 100644 --- a/app/datatables/checkin_datatable.rb +++ b/app/datatables/checkin_datatable.rb @@ -1,21 +1,21 @@ -class CheckinDatatable < AjaxDatatablesRails::Base +class CheckinDatatable < ApplicationDatatable def_delegators :@view, :link_to, :manage_checkin_path, :display_datetime, :bold def view_columns @view_columns ||= { - first_name: { source: 'Questionnaire.first_name' }, - last_name: { source: 'Questionnaire.last_name' }, - checked_in: { source: 'Questionnaire.checked_in_at', searchable: false }, + first_name: { source: "Questionnaire.first_name" }, + last_name: { source: "Questionnaire.last_name" }, + checked_in: { source: "Questionnaire.checked_in_at", searchable: false }, } end private def about(record) - output = '' - output += [record.first_name, record.last_name].join(' ') + ' ' + output = "" + output += [record.first_name, record.last_name].join(" ") + " " output += 'Minor' if record.minor? - output += '
' + record.school.name + '' + output += "
" + record.school.name + "" output.html_safe end @@ -25,15 +25,13 @@ def data first_name: record.first_name, last_name: record.last_name, about: about(record), - checked_in: record.checked_in? ? "Yes".html_safe : 'No', - actions: "View".html_safe + checked_in: record.checked_in? ? "Yes".html_safe : "No", + actions: "View".html_safe, } end end - # rubocop:disable Naming/AccessorMethodName def get_raw_records Questionnaire.includes(:user, :school).references(:user, :school) end - # rubocop:enable Naming/AccessorMethodName end diff --git a/app/datatables/questionnaire_datatable.rb b/app/datatables/questionnaire_datatable.rb index 03f30bde5..fb220cbcf 100644 --- a/app/datatables/questionnaire_datatable.rb +++ b/app/datatables/questionnaire_datatable.rb @@ -1,40 +1,53 @@ -class QuestionnaireDatatable < AjaxDatatablesRails::Base - def_delegators :@view, :link_to, :manage_questionnaire_path, :manage_school_path, :current_user, :acc_status_class, :display_datetime, :bold +class QuestionnaireDatatable < ApplicationDatatable + def_delegators :@view, :link_to, :manage_questionnaire_path, :manage_school_path, :toggle_bus_captain_manage_bus_list_path, :current_user, :acc_status_class, :display_datetime, :bold def view_columns @view_columns ||= { - id: { source: 'Questionnaire.id', cond: :eq }, - first_name: { source: 'Questionnaire.first_name' }, - last_name: { source: 'Questionnaire.last_name' }, - email: { source: 'User.email' }, - phone: { source: 'Questionnaire.phone' }, - gender: { source: 'Questionnaire.gender' }, - date_of_birth: { source: 'Questionnaire.date_of_birth', searchable: false }, - role: { source: 'User.role', cond: :eq, searchable: false }, - acc_status: { source: 'Questionnaire.acc_status', searchable: true }, - checked_in: { source: 'Questionnaire.checked_in_at', searchable: false }, - school: { source: 'School.name' }, - created_at: { source: 'Questionnaire.created_at', searchable: false }, - dietary_restrictions: { source: 'Questionnaire.dietary_restrictions', searchable: true }, - special_needs: { source: 'Questionnaire.special_needs', searchable: true } + id: { source: "Questionnaire.id", cond: :eq }, + first_name: { source: "Questionnaire.first_name" }, + last_name: { source: "Questionnaire.last_name" }, + email: { source: "User.email" }, + phone: { source: "Questionnaire.phone" }, + gender: { source: "Questionnaire.gender" }, + date_of_birth: { source: "Questionnaire.date_of_birth", searchable: false }, + role: { source: "User.role", cond: :eq, searchable: false }, + acc_status: { source: "Questionnaire.acc_status", searchable: true }, + checked_in: { source: "Questionnaire.checked_in_at", searchable: false }, + boarded_bus: { source: "Questionnaire.boarded_bus_at", searchable: false }, + bus_captain: { source: "Questionnaire.is_bus_captain", searchable: false }, + school: { source: "School.name" }, + created_at: { source: "Questionnaire.created_at", searchable: false }, + dietary_restrictions: { source: "Questionnaire.dietary_restrictions", searchable: true }, + special_needs: { source: "Questionnaire.special_needs", searchable: true }, } end private def note(record) - output = '' + output = "" output += ' Minor' if record.minor? output += '' if record.bus_list_id? - output += 'Captain' if record.is_bus_captain? - output = '
' + output + '
' if output.present? + output += "Captain" if record.is_bus_captain? + output = '
' + output + "
" if output.present? output.html_safe end + def bus_captain(record) + return "No" unless record.bus_list_id? + return record.is_bus_captain? ? 'Yes' : "No" unless current_user.admin? + + if record.is_bus_captain? + link_to("Remove", toggle_bus_captain_manage_bus_list_path(record.bus_list, questionnaire_id: record.id, bus_captain: "0"), method: "post", class: "text-danger") + else + link_to("Promote", toggle_bus_captain_manage_bus_list_path(record.bus_list, questionnaire_id: record.id, bus_captain: "1"), method: "post", data: { confirm: "Are you sure you want to make #{record.full_name} a bus captain? They will receive a confirmation email." }) + end + end + def data records.map do |record| { - bulk: current_user.admin? ? "".html_safe : '', + bulk: current_user.admin? ? "".html_safe : "", link: link_to(''.html_safe, manage_questionnaire_path(record)), note: note(record), id: record.id, @@ -45,18 +58,28 @@ def data gender: record.gender, date_of_birth: record.date_of_birth_formatted, acc_status: "#{record.acc_status.titleize}".html_safe, - checked_in: record.checked_in? ? 'Yes'.html_safe : 'No', + checked_in: record.checked_in? ? 'Yes'.html_safe : "No", + boarded_bus: record.boarded_bus? ? 'Yes'.html_safe : "No", + bus_captain: bus_captain(record), school: link_to(record.school.name, manage_school_path(record.school)), - created_at: record.created_at.present? ? display_datetime(record.created_at) : '', + created_at: record.created_at.present? ? display_datetime(record.created_at) : "", dietary_restrictions: record.dietary_restrictions, - special_needs: record.special_needs + special_needs: record.special_needs, } end end - # rubocop:disable Naming/AccessorMethodName def get_raw_records - Questionnaire.includes(:user, :school).references(:user, :school) + records = Questionnaire.includes(:user, :school).references(:user, :school) + if @params[:school_id].present? + records = records.where(school_id: @params[:school_id]) + end + if @params[:bus_list_id].present? + records = records.where(bus_list_id: @params[:bus_list_id]) + end + if @params[:acc_status].present? + records = records.where(acc_status: @params[:acc_status]) + end + records end - # rubocop:enable Naming/AccessorMethodName end diff --git a/app/datatables/school_datatable.rb b/app/datatables/school_datatable.rb index cfd3ed0fe..bc742239c 100644 --- a/app/datatables/school_datatable.rb +++ b/app/datatables/school_datatable.rb @@ -1,13 +1,14 @@ -class SchoolDatatable < AjaxDatatablesRails::Base +class SchoolDatatable < ApplicationDatatable def_delegators :@view, :link_to, :manage_school_path, :bold def view_columns @view_columns ||= { - id: { source: 'School.id', cond: :eq }, - name: { source: 'School.name' }, - city: { source: 'School.city' }, - state: { source: 'School.state' }, - questionnaire_count: { source: 'School.questionnaire_count', searchable: false } + id: { source: "School.id", cond: :eq }, + name: { source: "School.name" }, + city: { source: "School.city" }, + state: { source: "School.state" }, + questionnaire_count: { source: "School.questionnaire_count", searchable: false }, + home_school: { source: "School.is_home", searchable: false }, } end @@ -20,14 +21,13 @@ def data name: link_to(bold(record.name), manage_school_path(record)), city: record.city, state: record.state, - questionnaire_count: record.questionnaire_count + questionnaire_count: record.questionnaire_count, + home_school: record.is_home ? 'Yes'.html_safe : 'No'.html_safe, } end end - # rubocop:disable Naming/AccessorMethodName def get_raw_records School.all end - # rubocop:enable Naming/AccessorMethodName end diff --git a/app/views/manage/application/_questionnaire_datatable.html.haml b/app/views/manage/application/_questionnaire_datatable.html.haml new file mode 100644 index 000000000..61f33683c --- /dev/null +++ b/app/views/manage/application/_questionnaire_datatable.html.haml @@ -0,0 +1,86 @@ +:ruby + params = { format: :json } + if defined?(scope_params) + params = params.merge(scope_params) + end + data_source = datatable_manage_questionnaires_path(params) + + columns ||= %w(link note first_name last_name email acc_status checked_in school created_at) + visible = -> (column, columns) { columns.include?(column) ? 'true' : 'false' } + + order ||= "15 desc" + bulk_actions = true unless defined?(bulk_actions) + + # Use default page length if not defined + page_length ||= nil + +%div + %table.datatable.table.table-striped.table-hover{ data: { "auto-datatable": true, source: data_source, "table-order": order, 'page-length': page_length } } + %thead + %tr + %th{'data-table': { orderable: 'false', data: 'bulk', visible: bulk_actions ? 'true' : 'false' }} + - if current_user.admin? + %input{ type: "checkbox", name: "select_allc", value: "1", data: { bulk_row_select: "" } } + %th{'data-table': { orderable: 'false', data: 'link', visible: visible.call('link', columns) }} + %th{'data-table': { orderable: 'false', data: 'note', visible: visible.call('note', columns) }} + %th{'data-table': { orderable: 'true', data: 'id', visible: visible.call('id', columns) }} ID + %th{'data-table': { orderable: 'true', data: 'first_name', visible: visible.call('first_name', columns) }} First name + %th{'data-table': { orderable: 'true', data: 'last_name', visible: visible.call('last_name', columns) }} Last name + %th{'data-table': { orderable: 'true', data: 'email', visible: visible.call('email', columns) }} Email + %th{'data-table': { orderable: 'true', data: 'phone', visible: visible.call('phone', columns) }} Phone + %th{'data-table': { orderable: 'true', data: 'gender', visible: visible.call('gender', columns) }} Gender + %th{'data-table': { orderable: 'true', data: 'date_of_birth', visible: visible.call('date_of_birth', columns) }} Date of birth + %th{'data-table': { orderable: 'true', data: 'acc_status', visible: visible.call('acc_status', columns) }} Status + %th{'data-table': { orderable: 'true', data: 'checked_in', visible: visible.call('checked_in', columns) }} Checked in + %th{'data-table': { orderable: 'true', data: 'boarded_bus', visible: visible.call('boarded_bus', columns) }} Boarded bus + %th{'data-table': { orderable: 'true', data: 'bus_captain', visible: visible.call('bus_captain', columns) }} Bus captain + %th{'data-table': { orderable: 'true', data: 'school', visible: visible.call('school', columns) }} School + %th{'data-table': { orderable: 'true', data: 'created_at', visible: visible.call('created_at', columns) }} Applied on + %th{'data-table': { orderable: 'true', data: 'dietary_restrictions', visible: visible.call('dietary_restrictions', columns) }} Dietary restrictions + %th{'data-table': { orderable: 'true', data: 'special_needs', visible: visible.call('special_needs', columns) }} Special needs + %tbody + %tfoot + %tr + %th + %th + %th + %th + %input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'ID'} + %th + %input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'First name'} + %th + %input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'Last name'} + %th + %input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'Email'} + %th + %input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'Phone'} + %th + %input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'Gender'} + %th + %th + %select.form-control.form-control-sm + %option{value: ''} Status + - Questionnaire::POSSIBLE_ACC_STATUS.each do |key, value| + %option{value: key}= value + %th + %th + %th + %th + %input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'School'} + %th + %th + %input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'Dietary restrictions'} + %th + %input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'Special needs'} + + + - if bulk_actions + .row + .col-sm-7.col-lg-6 + %br + .card + .card-body + %h5.card-title Bulk Action + = bs_vertical_simple_form Questionnaire.new, url: bulk_apply_manage_questionnaires_path, html: { data: { bulk_row_edit: true } } do |f| + = 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." + = f.button :submit, value: "Update Status", data: { bulk_row_edit: true }, class: 'btn-primary' diff --git a/app/views/manage/bus_lists/show.html.haml b/app/views/manage/bus_lists/show.html.haml index 2a8e3d1f3..7534a3ad1 100644 --- a/app/views/manage/bus_lists/show.html.haml +++ b/app/views/manage/bus_lists/show.html.haml @@ -47,6 +47,9 @@ Passengers %small.text-muted (#{@bus_list.passengers.count} total, #{@bus_list.boarded_passengers.count} boarded, #{@bus_list.checked_in_passengers.count} checked in) + = render "questionnaire_datatable", scope_params: { bus_list_id: @bus_list.id, acc_status: 'rsvp_confirmed' }, columns: %w(link first_name last_name email phone checked_in boarded_bus bus_captain school), order: '13 desc, 15 desc', bulk_actions: false + + %h4.mt-4.pb-2 Interested Bus Captains %table.table %thead %tr @@ -56,17 +59,10 @@ %th Email %th Phone Number %th School - %th Boarded bus? - %th Checked in? - %th Bus Captain + - if current_user.admin? + %th Actions %tbody - - was_bus_captain = false - - @bus_list.passengers.reorder('is_bus_captain DESC, last_name ASC').each do |p| - - # Visual separator between captains and passengers - - if was_bus_captain && !p.is_bus_captain - %tr - %td{colspan: 9} - - was_bus_captain = p.is_bus_captain + - @bus_list.passengers.select { |q| q.bus_captain_interest }.each do |p| %tr %td= link_to ''.html_safe, manage_questionnaire_path(p) %td= p.first_name @@ -74,45 +70,12 @@ %td= p.email %td= phone_link_to p.phone %td= link_to p.school.name, manage_school_path(p.school) - %td= p.boarded_bus? ? 'Yes'.html_safe : 'No' - %td= p.checked_in? ? 'Yes'.html_safe : 'No' - if current_user.admin? %td - if p.is_bus_captain? - = link_to "Remove", toggle_bus_captain_manage_bus_list_path(@bus_list, questionnaire_id: p.id, bus_captain: '0'), method: 'post', class: 'text-danger' + = link_to "Remove Bus Captain", toggle_bus_captain_manage_bus_list_path(@bus_list, questionnaire_id: p.id, bus_captain: '0'), method: 'post', class: 'text-danger' - else - = link_to "Promote", toggle_bus_captain_manage_bus_list_path(@bus_list, questionnaire_id: p.id, bus_captain: '1'), method: 'post', data: { confirm: "Are you sure you want to make #{p.full_name} a bus captain? They will receive a confirmation email." } - - else - %td= p.is_bus_captain? ? "Yes" : "No" - - - if @bus_list.needs_bus_captain - %h4.mt-4.pb-2 Possible Bus Captains - %table.table - %thead - %tr - %th - %th First Name - %th Last Name - %th Email - %th Phone Number - %th School - - if current_user.admin? - %th Actions - %tbody - - @bus_list.passengers.select { |q| q.bus_captain_interest }.each do |p| - %tr - %td= link_to ''.html_safe, manage_questionnaire_path(p) - %td= p.first_name - %td= p.last_name - %td= p.email - %td= phone_link_to p.phone - %td= link_to p.school.name, manage_school_path(p.school) - - if current_user.admin? - %td - - if p.is_bus_captain? - = link_to "Remove Bus Captain", toggle_bus_captain_manage_bus_list_path(@bus_list, questionnaire_id: p.id, bus_captain: '0'), method: 'post', class: 'text-danger' - - else - = link_to "Make Bus Captain", toggle_bus_captain_manage_bus_list_path(@bus_list, questionnaire_id: p.id, bus_captain: '1'), method: 'post', data: { confirm: 'Are you sure? This will send a confirmation email to the bus captain.' } + = link_to "Make Bus Captain", toggle_bus_captain_manage_bus_list_path(@bus_list, questionnaire_id: p.id, bus_captain: '1'), method: 'post', data: { confirm: 'Are you sure? This will send a confirmation email to the bus captain.' } .row.mt-2.mb-4 .col diff --git a/app/views/manage/dashboard/index.html.haml b/app/views/manage/dashboard/index.html.haml index 9abce5dc9..c0a070828 100644 --- a/app/views/manage/dashboard/index.html.haml +++ b/app/views/manage/dashboard/index.html.haml @@ -35,7 +35,7 @@ %p total checked in %h3= Questionnaire.where('boarded_bus_at > 0').count %p total boarded bus - = area_chart checkin_activity_data_manage_dashboard_index_path, colors: [orange, blue], library: { legend: { enabled: false } } + = area_chart checkin_activity_data_manage_dashboard_index_path, colors: [blue, grey], library: { legend: { enabled: false } } .row .col diff --git a/app/views/manage/questionnaires/index.html.haml b/app/views/manage/questionnaires/index.html.haml index 6bc5347d1..c81710f65 100644 --- a/app/views/manage/questionnaires/index.html.haml +++ b/app/views/manage/questionnaires/index.html.haml @@ -1,75 +1,11 @@ = render "layouts/manage/page_title", title: "Questionnaires" do = link_to "New Questionnaire", new_manage_questionnaire_path, class: "btn btn-sm btn-outline-secondary" -%div - %table.questionnaires.datatable.table.table-striped.table-hover{ "data-source" => datatable_manage_questionnaires_path(format: :json) } - %thead - %tr - %th - - if current_user.admin? - %input{ type: "checkbox", name: "select_allc", value: "1", data: { bulk_row_select: "" } } - %th - %th - %th ID - %th First name - %th Last name - %th Email - %th Phone - %th Gender - %th Date of birth - %th Status - %th Checked In - %th School - %th Applied on - %th Dietary restrictions - %th Special needs - %tbody - %tfoot - %tr - %th - %th - %th - %th - %input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'ID'} - %th - %input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'First name'} - %th - %input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'Last name'} - %th - %input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'Email'} - %th - %input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'Phone'} - %th - %input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'Gender'} - %th - %th - %select.form-control.form-control-sm - %option{value: ''} Status - - Questionnaire::POSSIBLE_ACC_STATUS.each do |key, value| - %option{value: key}= value - %th - %th - %input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'School'} - %th - %th - %input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'Dietary restrictions'} - %th - %input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'Special needs'} += render "questionnaire_datatable" +%hr - .row - .col-sm-7.col-lg-6 - %br - .card - .card-body - %h5.card-title Bulk Action - = bs_vertical_simple_form Questionnaire.new, url: bulk_apply_manage_questionnaires_path, html: { data: { bulk_row_edit: true } } do |f| - = 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." - = f.button :submit, value: "Update Status", data: { bulk_row_edit: true }, class: 'btn-primary' - - %hr - - = render 'triggered_email_summary' += render 'triggered_email_summary' .mb-4 = render 'docs_link', title: 'Questionnaire documentation', url: 'https://coderit.org/hackathon-manager/docs/questionnaires' diff --git a/app/views/manage/schools/_form.html.haml b/app/views/manage/schools/_form.html.haml index a5565df14..b7f36b2bb 100644 --- a/app/views/manage/schools/_form.html.haml +++ b/app/views/manage/schools/_form.html.haml @@ -7,6 +7,7 @@ .form-inputs = f.input :name + = f.input :is_home = f.input :address = f.input :city = f.input :state diff --git a/app/views/manage/schools/index.html.haml b/app/views/manage/schools/index.html.haml index ac76b2d07..3e9978901 100644 --- a/app/views/manage/schools/index.html.haml +++ b/app/views/manage/schools/index.html.haml @@ -10,6 +10,7 @@ %th City %th State %th Count + %th Home? %tbody %tfoot %tr @@ -21,3 +22,4 @@ %input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'City'} %th %input.form-control.form-control-sm{autocomplete: 'off', placeholder: 'State'} + %th diff --git a/app/views/manage/schools/show.html.haml b/app/views/manage/schools/show.html.haml index eb071ca54..5874dcdeb 100644 --- a/app/views/manage/schools/show.html.haml +++ b/app/views/manage/schools/show.html.haml @@ -40,6 +40,12 @@ = link_to link, target: '_blank' do Search in Google Maps %span.fa.fa-external-link.icon-space-l-half + %dt.col-md-4 Home school + %dd.col-md-8 + - if @school.is_home? + %span.badge.badge-success Home school + - else + %span.badge.badge-secondary Not home school .col-md-6 %h4.pb-0 Duplicate Names @@ -77,27 +83,11 @@ .row.mt-2 .col - %h4.pb-0 + %h4.border-bottom.pb-2.mb-3 Questionnaires %small.text-muted (#{@school.questionnaires.count} total, #{@school.questionnaires.count { |q| q.checked_in? }} checked in) - %table.table - %thead - %tr - %th - %th First Name - %th Last Name - %th Email - %th Status - %th Checked In? - %tbody - - @school.questionnaires.order(:acc_status).each do |q| - %tr - %td= link_to ''.html_safe, manage_questionnaire_path(q) - %td= q.first_name - %td= q.last_name - %td= q.email - %td= "#{Questionnaire::POSSIBLE_ACC_STATUS[q.acc_status]}".html_safe - %td= q.checked_in? ? "Yes" : "No" + += 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) .row.mt-2.mb-4 .col-lg-6 diff --git a/config/initializers/ajax_datatables_rails.rb b/config/initializers/ajax_datatables_rails.rb index db81d9c63..9e327b5c2 100644 --- a/config/initializers/ajax_datatables_rails.rb +++ b/config/initializers/ajax_datatables_rails.rb @@ -1,7 +1,4 @@ AjaxDatatablesRails.configure do |config| # available options for db_adapter are: :pg, :mysql, :mysql2, :sqlite, :sqlite3 config.db_adapter = :mysql2 - - # available options for orm are: :active_record, :mongoid - config.orm = :active_record end diff --git a/config/locales/en.yml b/config/locales/en.yml index 58d42d539..d066d6f0a 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -50,6 +50,8 @@ en: type: Bulk emails are sent once, manually. Automated emails are sent upon a desired trigger/event. name: A friendly name to recognize this email. Applicants won't see this. trigger: Sent automatically when a new or updated applicant matches this criteria. Does not send to anyone already matching this criteria. + school: + is_home: The "home" school is separated from all other schools on dashboard metrics. hackathon_config: registration_is_open: Specify that registration is open. This does not block registration; it only changes messaging around it. event_is_over: Specify that the event is over @@ -102,6 +104,8 @@ en: user: email: joe@example.com labels: + school: + is_home: Home school user: is_active: Login access hackathon_config: diff --git a/db/migrate/20190529190615_add_is_home_to_schools.rb b/db/migrate/20190529190615_add_is_home_to_schools.rb new file mode 100644 index 000000000..ecbc02dbf --- /dev/null +++ b/db/migrate/20190529190615_add_is_home_to_schools.rb @@ -0,0 +1,5 @@ +class AddIsHomeToSchools < ActiveRecord::Migration[5.2] + def change + add_column :schools, :is_home, :boolean, default: false + end +end diff --git a/db/schema.rb b/db/schema.rb index 4efd716b1..ba449877d 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2019_05_28_155025) do +ActiveRecord::Schema.define(version: 2019_05_29_190615) do create_table "active_storage_attachments", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| t.string "name", null: false @@ -241,6 +241,7 @@ t.datetime "created_at" t.datetime "updated_at" t.integer "questionnaire_count", default: 0 + t.boolean "is_home", default: false end create_table "settings", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| diff --git a/release.config.js b/release.config.js index d45f8a550..0a873f07e 100644 --- a/release.config.js +++ b/release.config.js @@ -27,6 +27,8 @@ const writerOpts = { commit.type = `Tests`; } else if (commit.type === `deploy`) { commit.type = `Deployment`; + } else if (commit.type === 'maint') { + commit.type = 'Maintenance'; } else if (discard) { return; } else if (commit.type === `build`) { diff --git a/test/factories/bus_list.rb b/test/factories/bus_list.rb index 56b6da22f..b9c54674e 100644 --- a/test/factories/bus_list.rb +++ b/test/factories/bus_list.rb @@ -5,6 +5,6 @@ "Bus List #{n}" end capacity { 50 } - notes { "Notes!" } + notes { "Notes!" } end end diff --git a/test/factories/fips.rb b/test/factories/fips.rb index 492f18c2b..449a23339 100644 --- a/test/factories/fips.rb +++ b/test/factories/fips.rb @@ -1,7 +1,7 @@ FactoryBot.define do factory :fips do - fips_code { "36055" } - city { "Rochester" } - state { "NY" } + fips_code { "36055" } + city { "Rochester" } + state { "NY" } end end diff --git a/test/factories/message.rb b/test/factories/message.rb index 0dc7fc771..ec5fe8fce 100644 --- a/test/factories/message.rb +++ b/test/factories/message.rb @@ -1,11 +1,11 @@ FactoryBot.define do factory :message do - type { "bulk" } - name { "Message Name" } - subject { "Message Subject" } - recipients { ["all"] } - body { "Hello world!" } - queued_at { nil } + type { "bulk" } + name { "Message Name" } + subject { "Message Subject" } + recipients { ["all"] } + body { "Hello world!" } + queued_at { nil } delivered_at { nil } end end diff --git a/test/factories/questionnaire.rb b/test/factories/questionnaire.rb index f3cdeb01b..1498ca792 100644 --- a/test/factories/questionnaire.rb +++ b/test/factories/questionnaire.rb @@ -1,26 +1,26 @@ FactoryBot.define do factory :questionnaire do - first_name { "John" } - last_name { "Doe" } - phone { "(123) 456-7890" } - international { false } - date_of_birth { Date.today - 20.years } - experience { "first" } - interest { "design" } - school_id { create(:school).id } - shirt_size { "Unisex - M" } - dietary_restrictions { "" } - special_needs { "" } - agreement_accepted { true } + first_name { "John" } + last_name { "Doe" } + phone { "(123) 456-7890" } + international { false } + date_of_birth { Date.today - 20.years } + experience { "first" } + interest { "design" } + school_id { create(:school).id } + shirt_size { "Unisex - M" } + dietary_restrictions { "" } + special_needs { "" } + agreement_accepted { true } code_of_conduct_accepted { true } data_sharing_accepted { true } - can_share_info { true } - gender { "Male" } - major { "Computer Science" } - level_of_study { "University (Undergraduate)" } - graduation_year { Date.today.year } - race_ethnicity { "Other" } - why_attend { "This sounds cool" } + can_share_info { true } + gender { "Male" } + major { "Computer Science" } + level_of_study { "University (Undergraduate)" } + graduation_year { Date.today.year } + race_ethnicity { "Other" } + why_attend { "This sounds cool" } association :user end diff --git a/test/factories/school.rb b/test/factories/school.rb index e4e82b959..b08e325ba 100644 --- a/test/factories/school.rb +++ b/test/factories/school.rb @@ -8,8 +8,9 @@ "University of Rails #{n}" end address { "123 Fake Street" } - city { "Rochester" } - state { "NY" } + city { "Rochester" } + state { "NY" } questionnaire_count { 0 } + is_home { false } end end diff --git a/test/factories/temp_doorkeeper.rb b/test/factories/temp_doorkeeper.rb index bec60097f..d960e8704 100644 --- a/test/factories/temp_doorkeeper.rb +++ b/test/factories/temp_doorkeeper.rb @@ -4,9 +4,9 @@ factory :access_grant, class: "Doorkeeper::AccessGrant" do sequence(:resource_owner_id) { |n| n } application - redirect_uri { 'https://app.com/callback' } + redirect_uri { "https://app.com/callback" } expires_in { 100 } - scopes { 'public write' } + scopes { "public write" } end factory :access_token, class: "Doorkeeper::AccessToken" do @@ -21,7 +21,7 @@ factory :application, class: "Doorkeeper::Application" do sequence(:name) { |n| "Application #{n}" } - redirect_uri { 'https://app.com/callback' } + redirect_uri { "https://app.com/callback" } end # do not name this factory :user, otherwise it will conflict with factories diff --git a/vendor/cache/ajax-datatables-rails-0.4.3.gem b/vendor/cache/ajax-datatables-rails-0.4.3.gem deleted file mode 100644 index 46935ba82..000000000 Binary files a/vendor/cache/ajax-datatables-rails-0.4.3.gem and /dev/null differ diff --git a/vendor/cache/ajax-datatables-rails-1.0.0.gem b/vendor/cache/ajax-datatables-rails-1.0.0.gem new file mode 100644 index 000000000..6700494f5 Binary files /dev/null and b/vendor/cache/ajax-datatables-rails-1.0.0.gem differ diff --git a/vendor/cache/aws-partitions-1.164.0.gem b/vendor/cache/aws-partitions-1.164.0.gem deleted file mode 100644 index 4a39c0f8b..000000000 Binary files a/vendor/cache/aws-partitions-1.164.0.gem and /dev/null differ diff --git a/vendor/cache/aws-partitions-1.168.0.gem b/vendor/cache/aws-partitions-1.168.0.gem new file mode 100644 index 000000000..6232aad83 Binary files /dev/null and b/vendor/cache/aws-partitions-1.168.0.gem differ diff --git a/vendor/cache/aws-sdk-core-3.52.1.gem b/vendor/cache/aws-sdk-core-3.54.0.gem similarity index 52% rename from vendor/cache/aws-sdk-core-3.52.1.gem rename to vendor/cache/aws-sdk-core-3.54.0.gem index 82cffacbb..620230c61 100644 Binary files a/vendor/cache/aws-sdk-core-3.52.1.gem and b/vendor/cache/aws-sdk-core-3.54.0.gem differ diff --git a/vendor/cache/aws-sdk-kms-1.20.0.gem b/vendor/cache/aws-sdk-kms-1.20.0.gem deleted file mode 100644 index e1ca7235b..000000000 Binary files a/vendor/cache/aws-sdk-kms-1.20.0.gem and /dev/null differ diff --git a/vendor/cache/aws-sdk-kms-1.21.0.gem b/vendor/cache/aws-sdk-kms-1.21.0.gem new file mode 100644 index 000000000..a4479e45b Binary files /dev/null and b/vendor/cache/aws-sdk-kms-1.21.0.gem differ diff --git a/vendor/cache/aws-sdk-s3-1.39.0.gem b/vendor/cache/aws-sdk-s3-1.39.0.gem deleted file mode 100644 index f8724c3b8..000000000 Binary files a/vendor/cache/aws-sdk-s3-1.39.0.gem and /dev/null differ diff --git a/vendor/cache/aws-sdk-s3-1.40.0.gem b/vendor/cache/aws-sdk-s3-1.40.0.gem new file mode 100644 index 000000000..03e1ef28f Binary files /dev/null and b/vendor/cache/aws-sdk-s3-1.40.0.gem differ diff --git a/vendor/cache/blazer-2.0.1.gem b/vendor/cache/blazer-2.0.1.gem deleted file mode 100644 index 4f39aa40b..000000000 Binary files a/vendor/cache/blazer-2.0.1.gem and /dev/null differ diff --git a/vendor/cache/blazer-2.0.2.gem b/vendor/cache/blazer-2.0.2.gem new file mode 100644 index 000000000..4c7174195 Binary files /dev/null and b/vendor/cache/blazer-2.0.2.gem differ diff --git a/vendor/cache/capybara-3.20.2.gem b/vendor/cache/capybara-3.20.2.gem deleted file mode 100644 index 0aaa559ab..000000000 Binary files a/vendor/cache/capybara-3.20.2.gem and /dev/null differ diff --git a/vendor/cache/capybara-3.21.0.gem b/vendor/cache/capybara-3.21.0.gem new file mode 100644 index 000000000..36f96f21b Binary files /dev/null and b/vendor/cache/capybara-3.21.0.gem differ diff --git a/vendor/cache/chartkick-3.0.2.gem b/vendor/cache/chartkick-3.0.2.gem deleted file mode 100644 index 4d0c7450f..000000000 Binary files a/vendor/cache/chartkick-3.0.2.gem and /dev/null differ diff --git a/vendor/cache/chartkick-3.1.0.gem b/vendor/cache/chartkick-3.1.0.gem new file mode 100644 index 000000000..9c47748ac Binary files /dev/null and b/vendor/cache/chartkick-3.1.0.gem differ diff --git a/vendor/cache/coffee-rails-4.2.2.gem b/vendor/cache/coffee-rails-4.2.2.gem deleted file mode 100644 index 762e50e5d..000000000 Binary files a/vendor/cache/coffee-rails-4.2.2.gem and /dev/null differ diff --git a/vendor/cache/coffee-script-2.4.1.gem b/vendor/cache/coffee-script-2.4.1.gem deleted file mode 100644 index 7e4066d15..000000000 Binary files a/vendor/cache/coffee-script-2.4.1.gem and /dev/null differ diff --git a/vendor/cache/coffee-script-source-1.12.2.gem b/vendor/cache/coffee-script-source-1.12.2.gem deleted file mode 100644 index 80fabc691..000000000 Binary files a/vendor/cache/coffee-script-source-1.12.2.gem and /dev/null differ diff --git a/vendor/cache/groupdate-4.1.1.gem b/vendor/cache/groupdate-4.1.1.gem deleted file mode 100644 index ee359361e..000000000 Binary files a/vendor/cache/groupdate-4.1.1.gem and /dev/null differ diff --git a/vendor/cache/groupdate-4.1.2.gem b/vendor/cache/groupdate-4.1.2.gem new file mode 100644 index 000000000..aa86f8f41 Binary files /dev/null and b/vendor/cache/groupdate-4.1.2.gem differ diff --git a/vendor/cache/haml-5.1.0.gem b/vendor/cache/haml-5.1.0.gem deleted file mode 100644 index ebff43e93..000000000 Binary files a/vendor/cache/haml-5.1.0.gem and /dev/null differ diff --git a/vendor/cache/haml-5.1.1.gem b/vendor/cache/haml-5.1.1.gem new file mode 100644 index 000000000..61131b6d9 Binary files /dev/null and b/vendor/cache/haml-5.1.1.gem differ diff --git a/vendor/cache/haml-rails-1.0.0.gem b/vendor/cache/haml-rails-1.0.0.gem deleted file mode 100644 index af3a5bdd2..000000000 Binary files a/vendor/cache/haml-rails-1.0.0.gem and /dev/null differ diff --git a/vendor/cache/haml-rails-2.0.1.gem b/vendor/cache/haml-rails-2.0.1.gem new file mode 100644 index 000000000..7acaf7723 Binary files /dev/null and b/vendor/cache/haml-rails-2.0.1.gem differ diff --git a/vendor/cache/hashdiff-0.3.9.gem b/vendor/cache/hashdiff-0.3.9.gem deleted file mode 100644 index 2d5d8f260..000000000 Binary files a/vendor/cache/hashdiff-0.3.9.gem and /dev/null differ diff --git a/vendor/cache/hashdiff-0.4.0.gem b/vendor/cache/hashdiff-0.4.0.gem new file mode 100644 index 000000000..aff22f011 Binary files /dev/null and b/vendor/cache/hashdiff-0.4.0.gem differ diff --git a/vendor/cache/jwt-2.1.0.gem b/vendor/cache/jwt-2.1.0.gem deleted file mode 100644 index ebfe13720..000000000 Binary files a/vendor/cache/jwt-2.1.0.gem and /dev/null differ diff --git a/vendor/cache/jwt-2.2.1.gem b/vendor/cache/jwt-2.2.1.gem new file mode 100644 index 000000000..474e73ef0 Binary files /dev/null and b/vendor/cache/jwt-2.2.1.gem differ diff --git a/vendor/cache/public_suffix-3.0.3.gem b/vendor/cache/public_suffix-3.0.3.gem deleted file mode 100644 index f83ab3eab..000000000 Binary files a/vendor/cache/public_suffix-3.0.3.gem and /dev/null differ diff --git a/vendor/cache/public_suffix-3.1.0.gem b/vendor/cache/public_suffix-3.1.0.gem new file mode 100644 index 000000000..f7b626e00 Binary files /dev/null and b/vendor/cache/public_suffix-3.1.0.gem differ diff --git a/vendor/cache/regexp_parser-1.5.0.gem b/vendor/cache/regexp_parser-1.5.0.gem deleted file mode 100644 index dbc38cd1c..000000000 Binary files a/vendor/cache/regexp_parser-1.5.0.gem and /dev/null differ diff --git a/vendor/cache/regexp_parser-1.5.1.gem b/vendor/cache/regexp_parser-1.5.1.gem new file mode 100644 index 000000000..871f32e7d Binary files /dev/null and b/vendor/cache/regexp_parser-1.5.1.gem differ diff --git a/vendor/cache/rollbar-2.19.4.gem b/vendor/cache/rollbar-2.19.4.gem deleted file mode 100644 index 1e6dee029..000000000 Binary files a/vendor/cache/rollbar-2.19.4.gem and /dev/null differ diff --git a/vendor/cache/rollbar-2.20.0.gem b/vendor/cache/rollbar-2.20.0.gem new file mode 100644 index 000000000..a3c2ece47 Binary files /dev/null and b/vendor/cache/rollbar-2.20.0.gem differ diff --git a/vendor/cache/ruby-progressbar-1.10.0.gem b/vendor/cache/ruby-progressbar-1.10.0.gem deleted file mode 100644 index 6a344a7e8..000000000 Binary files a/vendor/cache/ruby-progressbar-1.10.0.gem and /dev/null differ diff --git a/vendor/cache/ruby-progressbar-1.10.1.gem b/vendor/cache/ruby-progressbar-1.10.1.gem new file mode 100644 index 000000000..519968f23 Binary files /dev/null and b/vendor/cache/ruby-progressbar-1.10.1.gem differ diff --git a/vendor/cache/rubyzip-1.2.2.gem b/vendor/cache/rubyzip-1.2.2.gem deleted file mode 100644 index 8daf6102d..000000000 Binary files a/vendor/cache/rubyzip-1.2.2.gem and /dev/null differ diff --git a/vendor/cache/rubyzip-1.2.3.gem b/vendor/cache/rubyzip-1.2.3.gem new file mode 100644 index 000000000..dbf335daf Binary files /dev/null and b/vendor/cache/rubyzip-1.2.3.gem differ diff --git a/vendor/cache/selenium-webdriver-3.142.2.gem b/vendor/cache/selenium-webdriver-3.142.3.gem similarity index 77% rename from vendor/cache/selenium-webdriver-3.142.2.gem rename to vendor/cache/selenium-webdriver-3.142.3.gem index f303da4ef..fc9f699dc 100644 Binary files a/vendor/cache/selenium-webdriver-3.142.2.gem and b/vendor/cache/selenium-webdriver-3.142.3.gem differ diff --git a/vendor/cache/skylight-4.0.1.gem b/vendor/cache/skylight-4.0.1.gem deleted file mode 100644 index 118d07a62..000000000 Binary files a/vendor/cache/skylight-4.0.1.gem and /dev/null differ diff --git a/vendor/cache/skylight-4.0.2.gem b/vendor/cache/skylight-4.0.2.gem new file mode 100644 index 000000000..ba2192920 Binary files /dev/null and b/vendor/cache/skylight-4.0.2.gem differ diff --git a/vendor/cache/skylight-core-4.0.1.gem b/vendor/cache/skylight-core-4.0.1.gem deleted file mode 100644 index e818d42f5..000000000 Binary files a/vendor/cache/skylight-core-4.0.1.gem and /dev/null differ diff --git a/vendor/cache/skylight-core-4.0.2.gem b/vendor/cache/skylight-core-4.0.2.gem new file mode 100644 index 000000000..f127aa9cd Binary files /dev/null and b/vendor/cache/skylight-core-4.0.2.gem differ