diff --git a/.gitignore b/.gitignore index c33bf252..ecdaea19 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ !/tmp/.keep .DS_Store capybara-* +.vscode/ # Ignore Byebug command history file. .byebug_history diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index b238693d..e17dadb4 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -497,3 +497,79 @@ nav.email-templates-menu li a:hover { input.grey { background-color: #c4220d; } + +.grid-wrapper { + display: grid; + grid-template-columns: 200px 200px 200px; + margin-bottom: .5em; +} + +.info-wrapper { + display: flex; + /* justify-content: space-evenly; */ + margin-bottom: 1em; + font-weight: bold; + color: #fff; +} + +.info-wrapper .info { + border-right: 1px solid #ffff; + padding: 15px; + text-align: left; + width: 30em; +} + +.cc-gradient { + background: linear-gradient(to right, #28B4F0, #F0A0C8); +} + +.cc-gradient-reverse { + background: linear-gradient(to right, #F0A0C8, #28B4F0); +} + +.tag { + padding: 0 .7em; + font-size: 12px; + width: fit-content; + color: #fff; + border-radius: 5px; +} + +/* Printer styles */ + +@media print { + header, + input, + footer, + .top-menu { + display: none; + } + + body { + color: #000; + background-color: #fff; + } + + .container { + width: 100%; + } + + table { + break-inside: avoid; + } + + h2 { + page-break-inside: avoid; + margin-top: 30px; + } + + /* Hacky solution to make avoidance of page break work ^^ + https://stackoverflow.com/a/53742871/9328428 + */ + h2::after { + content: ""; + display: block; + height: 200px; + margin-bottom: -200px; + } +} \ No newline at end of file diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb index 69175778..768876a1 100644 --- a/app/controllers/admin/groups_controller.rb +++ b/app/controllers/admin/groups_controller.rb @@ -3,15 +3,116 @@ class Admin::GroupsController < ApplicationController before_action :require_admin before_action :find_event + GROUP_SIZE = 4 + def index + @event_groups = @event.event_groups + @coaches_count = @event.coach_applications.approved.size + @attendees_count = @event.applications.application_selected.size end + # An action to regenerate + # -> a controller method + # -> button (to call the action) + # -> a route + # -> isolate generate behaviour in its own method + def generate + fill_groups + @event_groups = @event.event_groups redirect_to admin_event_groups_path(@event), notice: "Groups successfully generated" end + def regenerate + @event_groups = @event.event_groups + @event_groups.destroy_all + @event.reload + + fill_groups + redirect_to admin_event_groups_path(@event), notice: "Groups successfully regenerated" + end + private + def fetch_by_key(object, key) + object[key] || [] + end + + def fill_groups + # create a group for each pair of coaches + @coaches = @event.coach_applications.approved.to_a + @coaches.each_slice(1).with_index do |group, index| + event_group = EventGroup.create(event: @event, name: "Group #{index + 1}") + group.each do |coach_application| + event_group.coach_applications << coach_application + end + end + + # get selected attendees from DB + @attendees = @event.applications.application_selected.confirmed.to_a + + grouped_attendees_by_language = @attendees.group_by do |element| + [element.language_de, element.language_en, element.os] + end + + attendees_de_mac = fetch_by_key(grouped_attendees_by_language, [true, false, "mac"]) + attendees_de_windows = fetch_by_key(grouped_attendees_by_language, [true, false, "windows"]) + attendees_de_linux = fetch_by_key(grouped_attendees_by_language, [true, false, "linux"]) + + attendees_en_mac = fetch_by_key(grouped_attendees_by_language, [false, true, "mac"]) + attendees_en_windows = fetch_by_key(grouped_attendees_by_language, [false, true, "windows"]) + attendees_en_linux = fetch_by_key(grouped_attendees_by_language, [false, true, "linux"]) + + attendees_de_en_mac = fetch_by_key(grouped_attendees_by_language, [true, true, "mac"]) + attendees_de_en_windows = fetch_by_key(grouped_attendees_by_language, [true, true, "windows"]) + attendees_de_en_linux = fetch_by_key(grouped_attendees_by_language, [true, true, "linux"]) + + attendees_de_mac_groups = attendees_de_mac.in_groups_of(GROUP_SIZE, false) + attendees_de_windows_groups = attendees_de_windows.in_groups_of(GROUP_SIZE, false) + attendees_de_linux_groups = attendees_de_linux.in_groups_of(GROUP_SIZE, false) + attendees_en_mac_groups = attendees_en_mac.in_groups_of(GROUP_SIZE, false) + attendees_en_windows_groups = attendees_en_windows.in_groups_of(GROUP_SIZE, false) + attendees_en_linux_groups = attendees_en_linux.in_groups_of(GROUP_SIZE, false) + + [attendees_de_mac_groups, attendees_en_mac_groups].each do |groups| + if groups.try :nonzero? + if (groups.last.size < GROUP_SIZE) + groups.last.concat(attendees_de_en_mac.pop(GROUP_SIZE - groups.last.size)) + end + end + end + + [attendees_de_linux_groups, attendees_en_linux_groups].each do |groups| + if groups.try :nonzero? + if(groups.last.size < GROUP_SIZE) + groups.last.concat(attendees_de_en_linux.pop(GROUP_SIZE - groups.last.size)) + end + end + end + + [attendees_de_windows_groups, attendees_en_windows_groups].each do |groups| + if groups.try :nonzero? + if(groups.last.size < GROUP_SIZE) + groups.last.concat(attendees_de_en_windows.pop(GROUP_SIZE - groups.last.size)) + end + end + end + + de_en_groups_mac = attendees_de_en_mac.in_groups_of(GROUP_SIZE, false) + de_en_groups_windows = attendees_de_en_windows.in_groups_of(GROUP_SIZE, false) + de_en_groups_linux = attendees_de_en_windows.in_groups_of(GROUP_SIZE, false) + + all_groups = attendees_de_mac_groups + attendees_de_windows_groups + attendees_de_linux_groups + attendees_en_mac_groups + attendees_en_windows_groups + attendees_en_linux_groups + de_en_groups_mac + de_en_groups_windows + de_en_groups_linux + + + # FIXME: This can cause attendees to not be assigned to event groups + @event.event_groups.each do |event_group| + group_to_add = all_groups.pop(1) + break if group_to_add.nil? + event_group.applications << group_to_add + end + end + def find_event @event = Event.find(params[:event_id]) end diff --git a/app/models/application.rb b/app/models/application.rb index 43c2aefc..d05ad55c 100644 --- a/app/models/application.rb +++ b/app/models/application.rb @@ -21,6 +21,7 @@ class Application < ApplicationRecord scope :cancelled, -> { where(state: :cancelled) } scope :not_marked_as_selected, -> { where(selected_on: nil) } scope :confirmed, -> { where(attendance_confirmed: true) } + scope :language_de, -> { where(language_de: true) } enum state: { rejected: 0, waiting_list: 1, application_selected: 2, cancelled: 3 } diff --git a/app/models/coach.rb b/app/models/coach.rb index ff6ce02d..cd7cf2c3 100644 --- a/app/models/coach.rb +++ b/app/models/coach.rb @@ -3,4 +3,5 @@ class Coach < ApplicationRecord belongs_to :user accepts_nested_attributes_for :user has_many :coach_applications + has_and_belongs_to_many :event_groups end diff --git a/app/models/coach_application.rb b/app/models/coach_application.rb index e6c195ce..01cbf0cb 100644 --- a/app/models/coach_application.rb +++ b/app/models/coach_application.rb @@ -5,6 +5,7 @@ class CoachApplication < ApplicationRecord accepts_nested_attributes_for :event scope :to_contact, -> { where(contacted_at: nil, state: :approved) } + scope :approved, ->{ where(state: :approved) } enum state: { pending: 0, approved: 1, rejected: 2, cancelled: 3 } diff --git a/app/models/event.rb b/app/models/event.rb index 0fc10e9f..4f05e0ef 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -1,6 +1,7 @@ class Event < ApplicationRecord has_many :applications has_many :coach_applications + has_many :event_groups before_create :copy_templates validates :name, :place, :scheduled_at, :application_start, :application_end, :confirmation_date, :start_time, :end_time, presence: true @@ -26,9 +27,9 @@ def name_and_date end def has_groups? - false + !event_groups.empty? end - + private def right_order_of_dates diff --git a/app/models/event_group.rb b/app/models/event_group.rb new file mode 100644 index 00000000..f1ab6678 --- /dev/null +++ b/app/models/event_group.rb @@ -0,0 +1,5 @@ +class EventGroup < ApplicationRecord + belongs_to :event + has_and_belongs_to_many :coach_applications, join_table: "event_groups_coach_applications" + has_and_belongs_to_many :applications, join_table: "event_groups_applications" +end diff --git a/app/views/admin/groups/index.html.erb b/app/views/admin/groups/index.html.erb index b057b590..3ff358c1 100644 --- a/app/views/admin/groups/index.html.erb +++ b/app/views/admin/groups/index.html.erb @@ -1,5 +1,71 @@ <% if @event.has_groups? %> -has Groups + +
| Attendees | +Coaches | +
|---|---|
|
+ <% event_group.applications.map do |application| %>
+
+
+ <%= application.name %>
+
+
+ <% if application.language_de === true && application.language_en === true %>
+ both languages
+ <% elsif application.language_de === true && application.language_en === false %>
+ German
+ <% else %>
+ English
+ <% end %>
+
+
+ <% if application.os === "mac" %>
+ Mac
+ <% elsif application.os === "windows" %>
+ Windows
+ <% elsif application.os === "linux" %>
+ Linux
+ <% end %>
+
+
+ <% end %>
+ |
+
+ <% event_group.coach_applications.map do |application| %>
+
+
+ <%= application.coach.name %>
+
+
+ <% if application.coach.language_de === true && application.coach.language_en === true %>
+ both languages
+ <% elsif application.coach.language_de === true && application.coach.language_en === false %>
+ German
+ <% else %>
+ English
+ <% end %>
+
+
+ <% end %>
+ |
+