Skip to content
Snippets Groups Projects
Commit c973de66 authored by Teal's avatar Teal
Browse files

feat: add separate iCal feed including unconfirmed

parent e0bacb59
No related branches found
No related tags found
No related merge requests found
......@@ -383,6 +383,7 @@ PLATFORMS
aarch64-linux
arm64-darwin-22
arm64-darwin-23
arm64-darwin-24
x86_64-linux
DEPENDENCIES
......@@ -414,4 +415,4 @@ RUBY VERSION
ruby 3.4.3p32
BUNDLED WITH
2.6.2
2.6.7
......@@ -97,13 +97,66 @@ class AssignmentsController < ApplicationController
respond_to do |format|
format.html # This will render the existing HTML view (assignments/by_user.html.erb)
format.ics do |variant|
# Determine if candidates should be included based on the action name or a parameter
# For the standard .ics feed, candidates are NOT included.
# A new action/route (e.g., by_user_with_candidates) will set params[:include_candidates]
should_include_candidates = params[:include_candidates] == "true" && include_candidate_sessions?
calendar = build_ical_for_user(@user, include_candidates: should_include_candidates)
calendar.publish
headers["Content-Type"] = "text/calendar; charset=UTF-8"
render plain: calendar.to_ical
end
end
end
# Potentially a new action for the candidates feed, or reuse by_user with a param
# For simplicity, let's assume we add a new route that points to by_user
# and sets a param to differentiate. Or, we can create a new action.
# Let's create a new action for clarity, though it will largely reuse by_user's logic.
def by_user_with_candidates
@user = User.find(params[:user_id])
# Ensure data is loaded similar to by_user if needed for other formats,
# but for .ics, build_ical_for_user will handle queries.
@active_assignments = @user.assignments.joins(session: :conference).where(conferences: { active: true }).includes(:session, session: [ :conference, :stage ])
@active_standby_assignments = @user.standby_assignments.joins(standby_block: :conference).where(conferences: { active: true }).includes(standby_block: :conference)
if include_candidate_sessions?
@active_candidates = @user.candidates.joins(session: :conference).where(conferences: { active: true }).includes(:session, session: [ :conference, :stage ])
end
respond_to do |format|
format.ics do
if include_candidate_sessions?
calendar = build_ical_for_user(@user, include_candidates: true)
calendar.publish
headers["Content-Type"] = "text/calendar; charset=UTF-8"
render plain: calendar.to_ical
else
# Or render an empty calendar, or raise an error, or redirect.
# For now, let's render an empty calendar if the feature is off but this endpoint is hit.
calendar = Icalendar::Calendar.new
tz = TZInfo::Timezone.get("UTC")
calendar.publish
headers["Content-Type"] = "text/calendar; charset=UTF-8"
render plain: calendar.to_ical, status: :forbidden # Or :not_found
end
end
# Potentially handle .html differently or redirect if direct access to this action via HTML is not desired
format.html { redirect_to by_user_assignments_path(@user), notice: "To include candidates, ensure the feature is enabled and use the specific iCal link." }
end
end
private
def build_ical_for_user(user, include_candidates: false)
calendar = Icalendar::Calendar.new
tz = TZInfo::Timezone.get("UTC") # Or user.time_zone if available and relevant
calendar.add_timezone tz.ical_timezone Time.now
# Add confirmed assignments from active conferences only
@user.assignments.joins(session: :conference).where(conferences: { active: true }).each do |assignment|
user.assignments.joins(session: :conference).where(conferences: { active: true }).each do |assignment|
session = assignment.session
assignees = session.assignments.map { |a| a.user.name }
desc = [
......@@ -127,19 +180,19 @@ class AssignmentsController < ApplicationController
calendar.add_event(event)
end
# Add candidate sessions from active conferences if feature flag is enabled
if include_candidate_sessions?
@user.candidates.joins(session: :conference).where(conferences: { active: true }).includes(:session).each do |candidate|
# Add candidate sessions from active conferences if requested and feature flag is enabled
if include_candidates && include_candidate_sessions?
user.candidates.joins(session: :conference).where(conferences: { active: true }).includes(:session).each do |candidate|
session = candidate.session
# Skip if user is already assigned to this session
next if @user.assignments.any? { |a| a.session_id == session.id }
next if user.assignments.any? { |a| a.session_id == session.id }
assignees = session.assignments.map { |a| a.user.name }
candidates = session.candidates.map { |c| c.user.name }
candidates_list = session.candidates.map { |c| c.user.name }
desc = [
"🤔 CANDIDATE SESSION - You've expressed interest in this session",
"Current Assignees: #{assignees.any? ? assignees.join(', ') : 'None yet'}",
"Other Candidates: #{candidates.reject { |name| name == @user.name }.join(', ')}",
"Other Candidates: #{candidates_list.reject { |name| name == user.name }.join(', ')}",
"Speakers: #{session.speakers.map(&:name).join(', ')}",
session.description
]
......@@ -162,9 +215,9 @@ class AssignmentsController < ApplicationController
end
# Add standby assignments from active conferences
@user.standby_assignments.joins(standby_block: :conference).where(conferences: { active: true }).each do |standby_assignment|
user.standby_assignments.joins(standby_block: :conference).where(conferences: { active: true }).each do |standby_assignment|
standby_block = standby_assignment.standby_block
other_assignees = standby_block.users.where.not(id: @user.id).map(&:name)
other_assignees = standby_block.users.where.not(id: user.id).map(&:name)
desc = [
"🛡️ STANDBY BLOCK - You are on standby for translation needs",
......@@ -186,16 +239,9 @@ class AssignmentsController < ApplicationController
event.append_custom_property("X-ALT-DESC;FMTTYPE=text/html", desc.join("<hr>"))
calendar.add_event(event)
end
calendar.publish
headers["Content-Type"] = "text/calendar; charset=UTF-8"
render plain: calendar.to_ical
end
end
calendar
end
private
def authorize_permission
super("manage_assignments")
end
......
......@@ -7,10 +7,15 @@
<%= link_to @user.name, user_assignments_path(@user), class: "text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300" %>
</h1>
<%= link_to user_assignments_path(@user, format: 'ics'), class: "btn btn-info-light ml-4" do %>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 24" fill="currentColor" aria-hidden="true" class="size-5 inline-block mr-1"><path fill-rule="evenodd" d="M5.75 2a.75.75 0 01.75.75V4h7V2.75a.75.75 0 011.5 0V4h.25A2.75 2.75 0 0118 6.75v8.5A2.75 2.75 0 0115.25 18H4.75A2.75 2.75 0 012 15.25v-8.5A2.75 2.75 0 014.75 4H5V2.75A.75.75 0 015.75 2zm-1 5.5c-.69 0-1.25.56-1.25 1.25v6.5c0 .69.56 1.25 1.25 1.25h10.5c.69 0 1.25-.56 1.25-1.25v-6.5c0-.69-.56-1.25-1.25-1.25H4.75z" clip-rule="evenodd"></path></svg> iCal
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 24" fill="currentColor" aria-hidden="true" class="size-5 inline-block mr-1"><path fill-rule="evenodd" d="M5.75 2a.75.75 0 01.75.75V4h7V2.75a.75.75 0 011.5 0V4h.25A2.75 2.75 0 0118 6.75v8.5A2.75 2.75 0 0115.25 18H4.75A2.75 2.75 0 012 15.25v-8.5A2.75 2.75 0 014.75 4H5V2.75A.75.75 0 015.75 2zm-1 5.5c-.69 0-1.25.56-1.25 1.25v6.5c0 .69.56 1.25 1.25 1.25h10.5c.69 0 1.25-.56 1.25-1.25v-6.5c0-.69-.56-1.25-1.25-1.25H4.75z" clip-rule="evenodd"></path></svg> iCal (Confirmed)
<% end %>
<% if @controller.send(:include_candidate_sessions?) %>
<%= link_to user_with_candidates_assignments_path(@user, format: 'ics'), class: "btn btn-warning-light ml-2" do %>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 24" fill="currentColor" aria-hidden="true" class="size-5 inline-block mr-1"><path fill-rule="evenodd" d="M5.75 2a.75.75 0 01.75.75V4h7V2.75a.75.75 0 011.5 0V4h.25A2.75 2.75 0 0118 6.75v8.5A2.75 2.75 0 0115.25 18H4.75A2.75 2.75 0 012 15.25v-8.5A2.75 2.75 0 014.75 4H5V2.75A.75.75 0 015.75 2zm-1 5.5c-.69 0-1.25.56-1.25 1.25v6.5c0 .69.56 1.25 1.25 1.25h10.5c.69 0 1.25-.56 1.25-1.25v-6.5c0-.69-.56-1.25-1.25-1.25H4.75z" clip-rule="evenodd"></path></svg> iCal (Incl. Unconfirmed)
<% end %>
<% end %>
</div>
<% if @active_candidates %>
<% if @active_candidates && @controller.send(:include_candidate_sessions?) %>
<div class="flex items-center">
<label class="inline-flex items-center cursor-pointer">
<input type="checkbox" id="showCandidates" class="sr-only peer" checked>
......
......@@ -74,6 +74,7 @@ Rails.application.routes.draw do
resources :assignments, only: [ :index ] do
get "for/:user_id", action: "by_user", on: :collection, as: :user
get "for/:user_id/with_candidates", action: "by_user_with_candidates", on: :collection, as: :user_with_candidates
end
resources :sessions, param: :ref_id
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment