diff --git a/README.md b/README.md index 969778243..b6f81a408 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ # Worldcon Programme Planning System +![Production version](https://img.shields.io/github/v/release/ChicagoWorldcon/planorama?label=production) +![Staging version](https://img.shields.io/github/v/release/ChicagoWorldcon/planorama?include_prereleases&label=staging) # Getting Started diff --git a/app/controllers/publication_dates_controller.rb b/app/controllers/publication_dates_controller.rb index 3048de63e..cbfa9d152 100644 --- a/app/controllers/publication_dates_controller.rb +++ b/app/controllers/publication_dates_controller.rb @@ -30,4 +30,12 @@ def reset def paginate false end + + def allowed_params + %i[ + id + lock_version + sent_external + ] + end end diff --git a/app/controllers/reports/people_reports_controller.rb b/app/controllers/reports/people_reports_controller.rb index 8a57da9fa..6ccb65e01 100644 --- a/app/controllers/reports/people_reports_controller.rb +++ b/app/controllers/reports/people_reports_controller.rb @@ -1,5 +1,107 @@ class Reports::PeopleReportsController < ApplicationController around_action :set_timezone + def social_media + authorize Person, policy_class: ReportPolicy + + people = SessionService.draft_people + + workbook = FastExcel.open(constant_memory: true) + worksheet = workbook.add_worksheet("Participant and Social Media") + + worksheet.append_row( + [ + 'Published Name', + 'Attendance Type', + 'Participant Status', + 'Bio', + 'Social Media' + ] + ) + + people.each do |person| + social = [] + social << "Twitter: https://twitter.com/#{person.twitter}" unless person.twitter.blank? + social << "Facebook: https://facebook.com/#{person.facebook}" unless person.facebook.blank? + social << "Website: #{person.website}" unless person.website.blank? + social << "Instagram: https://instagram.com/#{person.instagram}" unless person.instagram.blank? + social << "Twitch: https://twitch.tv/#{person.twitch}" unless person.twitch.blank? + social << "Youtube: https://youtube.com/#{person.youtube}" unless person.youtube.blank? + social << "TikTok: https://www.tiktok.com/@#{person.tiktok}" unless person.tiktok.blank? + social << "LinkedIn: https://linkedin.com/in/#{person.linkedin}" unless person.linkedin.blank? + social << "Other Social Media: #{person.othersocialmedia}" unless person.othersocialmedia.blank? + + worksheet.append_row( + [ + person.published_name, + person.attendance_type, + person.con_state, + person.bio, + social.join(",\n") + ] + ) + end + + send_data workbook.read_string, + filename: "ParticipantsSocialMedia-#{Time.now.strftime('%m-%d-%Y')}.xlsx", + disposition: 'attachment' + end + + def mis_matched_envs + authorize Person, policy_class: ReportPolicy + + results = PersonSchedule + .joins(:person) + .where( + %q(case + when (person_schedules.environment = 'in_person') then (people.attendance_type != 'in person' and people.attendance_type != 'hybrid') + when (person_schedules.environment = 'hybrid') then (people.attendance_type != 'in person' and people.attendance_type != 'hybrid') + when (person_schedules.environment = 'virtual') then (people.attendance_type != 'virtual' and people.attendance_type != 'hybrid') + end + ) + ) + .order("published_name asc, start_time asc") + + # Sessions: only scheduled sessions, + # only when virtual people are on in-person or hybrid sessions, or in-person people are on virtual sessions + workbook = FastExcel.open(constant_memory: true) + worksheet = workbook.add_worksheet("Mismatched Envs") + date_time_style = workbook.number_format("d mmm yyyy h:mm") + + worksheet.append_row( + [ + 'Published Name', + 'Primary Email', + 'Attendance Type', + 'Participant Status', + 'Session', + 'Room', + 'Start Time', + 'Session Environment' + ] + ) + + styles = [nil, nil, nil, nil, nil, nil, date_time_style, nil] + + results.each do |result| + worksheet.append_row( + [ + result.published_name, + result.person.primary_email&.email, + result.person.attendance_type, + result.person.con_state, + result.title, + result.room&.name, + result.session.start_time ? FastExcel.date_num(result.session.start_time, result.session.start_time.in_time_zone.utc_offset) : nil, + result.environment + ], + styles + ) + end + + send_data workbook.read_string, + filename: "PeopleOnMismatchedSessions-#{Time.now.strftime('%m-%d-%Y')}.xlsx", + disposition: 'attachment' + end def moderators authorize Person, policy_class: ReportPolicy diff --git a/app/controllers/reports/program_ops_reports_controller.rb b/app/controllers/reports/program_ops_reports_controller.rb index 5ba635770..4ad1e7e18 100644 --- a/app/controllers/reports/program_ops_reports_controller.rb +++ b/app/controllers/reports/program_ops_reports_controller.rb @@ -47,6 +47,226 @@ def virtual_people disposition: 'attachment' end + def session_minors + authorize Session, policy_class: Reports::ProgramOpsReportPolicy + + sessions = SessionService + .draft_sessions + .includes(:age_restriction) + + + workbook = FastExcel.open(constant_memory: true) + worksheet = workbook.add_worksheet("Session and Minor Info") + date_time_style = workbook.number_format("d mmm yyyy h:mm") + styles = [nil, nil, date_time_style] + + worksheet.append_row( + [ + 'Session', + 'Description', + 'Start Time', + 'Room', + 'Age Restriction', + 'Minors Participation' + ] + ) + + sessions.each do |session| + worksheet.append_row( + [ + session.title, + session.description, + session.start_time ? FastExcel.date_num(session.start_time, session.start_time.in_time_zone.utc_offset) : nil, + session.room&.name, + session.age_restriction&.name, + (session.minors_participation && session.minors_participation.size > 0) ? session.minors_participation.join(', ') : nil + ], + styles + ) + end + + send_data workbook.read_string, + filename: "SessionAndMinors-#{Time.now.strftime('%m-%d-%Y')}.xlsx", + disposition: 'attachment' + end + + def user_privileges + authorize Person, policy_class: Reports::ProgramOpsReportPolicy + + people = Person.includes(:convention_roles, :application_roles, :primary_email).order(:published_name) + + workbook = FastExcel.open(constant_memory: true) + worksheet = workbook.add_worksheet("People and Roles") + date_time_style = workbook.number_format("d mmm yyyy h:mm") + + worksheet.append_row( + [ + 'Primary Email', + 'Published Name', + 'Convention Roles', + 'Recently Logged In At' + # 'Application Roles' + ] + ) + people.each do |person| + worksheet.append_row( + [ + person.primary_email, + person.published_name, + person.convention_roles.collect{|r| r.role}.join(', '), + person.current_sign_in_at ? FastExcel.date_num(person.current_sign_in_at, person.current_sign_in_at.in_time_zone.utc_offset) : nil, + # person.convention_roles.collect{|r| r.application_roles.collect{|r| r.name}}.concat(person.application_roles.collect{|r| r.name}).join(', ') + ], + [nil, nil, nil, date_time_style] + ) + end + + send_data workbook.read_string, + filename: "UserPrivlages-#{Time.now.strftime('%m-%d-%Y')}.xlsx", + disposition: 'attachment' + end + + def room_signs + authorize SessionAssignment, policy_class: Reports::ProgramOpsReportPolicy + + # Need by room and time + sessions = SessionService + .published_sessions_unordered + # .order("rooms.name asc, start_time asc") + + # Room name, Day of week, sessions (title, start time, description, participant list with moderator marker). + grouped_sessions = sessions.group_by {|s| [s.room, s.start_time.strftime('%A'), s.start_time.strftime('%Y%j')]} + moderator = SessionAssignmentRoleType.find_by(name: 'Moderator') + participant = SessionAssignmentRoleType.find_by(name: 'Participant') + max_sessions = 0 + + workbook = FastExcel.open #(constant_memory: true) + worksheet = workbook.add_worksheet("Room Signs") + date_time_style = workbook.number_format("d mmm yyyy h:mm") + styles = [nil, nil, nil, date_time_style] + + worksheet.append_row([]) # For the header + + # one line per room per day + grouped_sessions.sort{|a,b| (a[0][0].name + a[0][2]) <=> (b[0][0].name + b[0][2]) }.each do |grp, sessions| + row = [grp[0].name, grp[1]] + styles = [nil, nil] + + sessions.sort{|a,b| a.start_time <=> b.start_time}.each do |session| + row.concat [ + # session.start_time.strftime('%A'), + session.title, + session.start_time ? FastExcel.date_num(session.start_time, session.start_time.in_time_zone.utc_offset) : nil, + session.description, + session.published_session_assignments.select{|a| a.session_assignment_role_type_id == moderator.id}.collect{|a| a.person.published_name}.join("; "), + session.published_session_assignments.select{|a| a.session_assignment_role_type_id == participant.id}.collect{|a| a.person.published_name}.join("; "), + ] + styles.concat [ + nil, date_time_style, nil, nil, nil + ] + end + max_sessions = sessions.size if sessions.size > max_sessions + + worksheet.append_row(row, styles) + end + + header = ['Room', 'Day'] + (0..max_sessions).each do |n| + header.concat ["Title #{n+1}", "Start Time #{n+1}", "Description #{n+1}", "Moderators #{n+1}", "Participants #{n+1}"] + end + worksheet.write_row(0, header) + + send_data workbook.read_string, + filename: "RoomSigns#{Time.now.strftime('%m-%d-%Y')}.xlsx", + disposition: 'attachment' + end + + def sign_up_sessions + authorize SessionAssignment, policy_class: Reports::ProgramOpsReportPolicy + + sessions = SessionService.draft_sessions.where('require_signup = true') + + workbook = FastExcel.open #(constant_memory: true) + worksheet = workbook.add_worksheet("Sessions requiring Signups") + date_time_style = workbook.number_format("d mmm yyyy h:mm") + + styles = [nil, nil, nil, date_time_style ] + + worksheet.append_row( + [ + 'Session', + 'Description', + 'Room', + 'Start Time', + 'Duration', + 'Format', + 'Participants', + 'Environment', + 'Max Signups' + ] + ) + + sessions.each do |session| + worksheet.append_row( + [ + session.title, + session.description, + session.room&.name, + session.start_time ? FastExcel.date_num(session.start_time, session.start_time.in_time_zone.utc_offset) : nil, + session.duration, + session.format&.name, + session.participant_assignments.collect{|pa| pa.person.published_name}.join(";\n"), + session.environment, + session.audience_size + ], + styles + ) + end + + send_data workbook.read_string, + filename: "SessionRequoringSignup-#{Time.now.strftime('%m-%d-%Y')}.xlsx", + disposition: 'attachment' + end + + def table_tents + authorize SessionAssignment, policy_class: Reports::ProgramOpsReportPolicy + + sessions = SessionService.published_sessions + moderator = SessionAssignmentRoleType.find_by(name: 'Moderator') + participant = SessionAssignmentRoleType.find_by(name: 'Participant') + + workbook = FastExcel.open #(constant_memory: true) + worksheet = workbook.add_worksheet("Table Tents") + + worksheet.append_row( + [ + 'Session', + 'Published Name', + 'Description', + 'Participant Notes', + 'Moderators', + 'Participants' + ] + ) + + sessions.each do |session| + session.published_session_assignments.each do |pa| + worksheet.append_row [ + session.title, + pa.person.published_name, + session.description, + session.participant_notes, + session.published_session_assignments.role(moderator).collect{|p| "#{p.person.published_name} (#{p.person.pronouns})" }.join(",\n"), + session.published_session_assignments.role(participant).collect{|p| "#{p.person.published_name} (#{p.person.pronouns})" }.join(",\n") + ] + end + end + + send_data workbook.read_string, + filename: "TableTents-#{Time.now.strftime('%m-%d-%Y')}.xlsx", + disposition: 'attachment' + end + def back_of_badge authorize SessionAssignment, policy_class: Reports::ProgramOpsReportPolicy diff --git a/app/controllers/reports/session_reports_controller.rb b/app/controllers/reports/session_reports_controller.rb index 0c5967041..58e2b2d01 100644 --- a/app/controllers/reports/session_reports_controller.rb +++ b/app/controllers/reports/session_reports_controller.rb @@ -1,6 +1,56 @@ class Reports::SessionReportsController < ApplicationController around_action :set_timezone + def session_needs + authorize SessionAssignment, policy_class: Reports::SessionReportPolicy + + sessions = SessionService.draft_sessions + + workbook = FastExcel.open(constant_memory: true) + worksheet = workbook.add_worksheet("Session Needs") + date_time_style = workbook.number_format("d mmm yyyy h:mm") + styles = [ + nil, date_time_style + ] + + worksheet.append_row( + [ + 'Session', + 'Start Time', + 'Room', + 'Environment', + 'Format', + 'Areas', + 'Required Room Features/Services', #room_notes + 'Tech/Hotel Notes', # + 'Room Setup' # room_set_id + ] + ) + + # require room features.services, tech/hotel notes, room setup + + sessions.each do |session| + worksheet.append_row( + [ + session.title, + session.start_time ? FastExcel.date_num(session.start_time, session.start_time.in_time_zone.utc_offset) : nil, + session.room&.name, + session.environment, + session.format&.name, + session.area_list.sort.join(';'), + session.room_notes, + session.tech_notes, + session.room_set&.name + ], + styles + ) + end + + send_data workbook.read_string, + filename: "SessionNeeds-#{Time.now.strftime('%m-%d-%Y')}.xlsx", + disposition: 'attachment' + end + def streamed_and_recorded authorize SessionAssignment, policy_class: Reports::SessionReportPolicy diff --git a/app/javascript/components/table_vue.vue b/app/javascript/components/table_vue.vue index 8833acbc6..dedd78a62 100644 --- a/app/javascript/components/table_vue.vue +++ b/app/javascript/components/table_vue.vue @@ -218,6 +218,7 @@ export default { if (to > this.totalRows) { to = this.totalRows } + if (this.totalRows == 0) from = 0 return `Showing ${from} to ${to} of ${this.totalRows} (${this.fullTotalRows} total records)` }, diff --git a/app/javascript/mailings/mailing_editor.vue b/app/javascript/mailings/mailing_editor.vue index d633d9176..0246aae8e 100644 --- a/app/javascript/mailings/mailing_editor.vue +++ b/app/javascript/mailings/mailing_editor.vue @@ -1,31 +1,19 @@