From 7430405e2bbc30880b4c4c2d85c9ed18add30002 Mon Sep 17 00:00:00 2001
From: Teal Starsong <git@teal.is>
Date: Tue, 27 May 2025 10:58:07 +0200
Subject: [PATCH] feat: add a separate ical feed including unconfirmed, make
 default show ony confirmed

---
 app/controllers/assignments_controller.rb | 15 ++++++++-------
 app/models/system_setting.rb              | 16 +++++++++++-----
 app/views/assignments/by_user.html.erb    |  4 ++--
 3 files changed, 21 insertions(+), 14 deletions(-)

diff --git a/app/controllers/assignments_controller.rb b/app/controllers/assignments_controller.rb
index 0c20e18..508bfaf 100644
--- a/app/controllers/assignments_controller.rb
+++ b/app/controllers/assignments_controller.rb
@@ -1,7 +1,7 @@
 require "icalendar/tzinfo"
 
 class AssignmentsController < ApplicationController
-  before_action :authorize_permission, except: %i[index by_user]
+  before_action :authorize_permission, except: %i[index by_user by_user_with_candidates]
   before_action :set_session, :set_users
 
   def index
@@ -90,7 +90,8 @@ class AssignmentsController < ApplicationController
     @active_standby_assignments = @user.standby_assignments.joins(standby_block: :conference).where(conferences: { active: true }).includes(standby_block: :conference)
 
     # Include candidates if feature flag is enabled
-    if include_candidate_sessions?
+    @show_candidates_feature_enabled = include_candidate_sessions? # Set instance variable
+    if @show_candidates_feature_enabled
       @active_candidates = @user.candidates.joins(session: :conference).where(conferences: { active: true }).includes(:session, session: [ :conference, :stage ])
     end
 
@@ -122,13 +123,14 @@ class AssignmentsController < ApplicationController
     # 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?
+    @show_candidates_feature_enabled = include_candidate_sessions? # Set instance variable
+    if @show_candidates_feature_enabled
       @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?
+        if @show_candidates_feature_enabled # Use instance variable
           calendar = build_ical_for_user(@user, include_candidates: true)
           calendar.publish
           headers["Content-Type"] = "text/calendar; charset=UTF-8"
@@ -257,8 +259,7 @@ class AssignmentsController < ApplicationController
 
   def include_candidate_sessions?
     # Feature flag to include candidate sessions in iCal feed
-    # Can be controlled via environment variable or system setting
-    ENV.fetch("INCLUDE_CANDIDATE_SESSIONS", "false").downcase == "true" ||
-      SystemSetting.include_candidate_sessions?
+    # Controlled via system setting
+    SystemSetting.include_candidate_sessions?
   end
 end
diff --git a/app/models/system_setting.rb b/app/models/system_setting.rb
index 6872d3d..fd50263 100644
--- a/app/models/system_setting.rb
+++ b/app/models/system_setting.rb
@@ -10,11 +10,17 @@ class SystemSetting < ApplicationRecord
 
   # Set the invitation token
   def self.set_invitation_token(token)
-    setting = find_or_initialize_by(key: "invitation_token")
-    setting.value = token.to_s
-    setting.description = "Token required for user registration/signup"
-    setting.setting_type = "string"
-    setting.save!
+    # Atomically find or create the record by its unique key.
+    # The block is only executed if a new record is being created.
+    setting = find_or_create_by!(key: "invitation_token") do |s|
+      s.description = "Token required for user registration/signup"
+      s.setting_type = "string"
+      # The token value will be set/updated outside the block.
+    end
+
+    # Update the value. If it was just created, this sets its initial value.
+    # If it already existed, its value is updated.
+    setting.update!(value: token.to_s)
     setting
   end
 
diff --git a/app/views/assignments/by_user.html.erb b/app/views/assignments/by_user.html.erb
index 4fb3049..44f3165 100644
--- a/app/views/assignments/by_user.html.erb
+++ b/app/views/assignments/by_user.html.erb
@@ -9,13 +9,13 @@
         <%= 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 (Confirmed)
         <% end %>
-        <% if @controller.send(:include_candidate_sessions?) %>
+        <% if @show_candidates_feature_enabled %>
           <%= 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 && @controller.send(:include_candidate_sessions?) %>
+      <% if @active_candidates && @show_candidates_feature_enabled %>
         <div class="flex items-center">
           <label class="inline-flex items-center cursor-pointer">
             <input type="checkbox" id="showCandidates" class="sr-only peer" checked>
-- 
GitLab