From 149b15f6b5a73f3439e4572c1113e153ee534d7a Mon Sep 17 00:00:00 2001
From: Teal <git@teal.is>
Date: Tue, 4 Mar 2025 18:57:41 +0100
Subject: [PATCH] Fixup

---
 app/jobs/pretalx/import_job.rb                |  48 +++++++-
 .../republica_2023_or_later/import_job.rb     |   5 +-
 app/models/filedrop_file.rb                   |   9 +-
 app/models/session.rb                         |   7 +-
 app/models/speaker.rb                         |   7 +-
 .../assignment_audit_subscriber.rb            |   2 +-
 app/subscribers/revision_subscriber.rb        |   2 +-
 app/views/layouts/application.html.erb        | 114 +++++++-----------
 config/environments/development.rb            |   2 +
 9 files changed, 109 insertions(+), 87 deletions(-)

diff --git a/app/jobs/pretalx/import_job.rb b/app/jobs/pretalx/import_job.rb
index db4f801..d0f1ee3 100644
--- a/app/jobs/pretalx/import_job.rb
+++ b/app/jobs/pretalx/import_job.rb
@@ -8,6 +8,41 @@ module Pretalx
     queue_as :default
     include ActionView::Helpers
 
+    # Class method to return required data fields
+    def self.required_data_fields
+      [ "schedule_url", "filedrop_url", "engelsystem_url", "heartbeat_url" ]
+    end
+
+    # Class method to return field metadata
+    def self.field_metadata
+      {
+        "schedule_url" => {
+          title: "Schedule URL",
+          description: "URL to the Pretalx schedule data in JSON format",
+          placeholder: "https://pretalx.com/api/events/<EVENT>/schedules/latest/",
+          required: true
+        },
+        "filedrop_url" => {
+          title: "Filedrop URL",
+          description: "URL to the filedrop service for speaker slides and materials",
+          placeholder: "https://filedrop.example.com/api/",
+          required: false
+        },
+        "engelsystem_url" => {
+          title: "Engelsystem URL",
+          description: "URL to the Engelsystem API for volunteer management",
+          placeholder: "https://engelsystem.example.com/api/",
+          required: false
+        },
+        "heartbeat_url" => {
+          title: "Heartbeat URL",
+          description: "URL to ping when the import is complete",
+          placeholder: "https://monitoring.example.com/ping/<ID>",
+          required: false
+        }
+      }
+    end
+
     def import_schedule(conference)
       response = HTTParty.get(conference.schedule_url)
       response.success? or return Rails.logger.error "Failed to fetch schedule from #{conference.schedule_url}"
@@ -62,7 +97,10 @@ module Pretalx
                 end
               end
               session.recorded = !session_data.fetch("do_not_record", false)
-              update_filedrop_data(session, filedrop_index[session.ref_id], conference.filedrop_url) if filedrop_index[session.ref_id]
+              if filedrop_index[session.ref_id]
+                update_filedrop_data(session, filedrop_index[session.ref_id],
+                                     conference.filedrop_url)
+              end
               session.save!
             end
           end
@@ -97,6 +135,7 @@ module Pretalx
 
         shifts_at_time.each do |shift|
           next unless session.stage.name == shift.dig("location", "name")
+
           session.engelsystem_id = shift["id"]
           session.engelsystem_url = shift["url"]
           session.save
@@ -129,13 +168,13 @@ module Pretalx
           },
           headers: { "Accept" => "application/json" },
           timeout: 30
-          )
+        )
         data = JSON.parse(response.body)
       rescue StandardError => e
         Rails.logger.warn("Filedrop response for #{session.ref_id} failed: #{e.message}")
         return {}
       end
-      if !data["talks"].is_a?(Array)
+      unless data["talks"].is_a?(Array)
         Rails.logger.warn("Filedrop index was incomplete")
         return {}
       end
@@ -172,7 +211,8 @@ module Pretalx
 
       # Add or update files
       filedrop_data["files"]&.each do |file_data|
-        session.filedrop_files.find_or_initialize_by(name: file_data["name"], checksum: file_data["meta"]["hash"]).tap do |file|
+        session.filedrop_files.find_or_initialize_by(name: file_data["name"],
+                                                     checksum: file_data["meta"]["hash"]).tap do |file|
           file.size = file_data["meta"]["size"]
           file.orig_created = parse_datetime_or_nil(session.conference, file_data["meta"]["created"])
           if file_data["url"].blank?
diff --git a/app/jobs/republica_2023_or_later/import_job.rb b/app/jobs/republica_2023_or_later/import_job.rb
index 1e69748..b484673 100644
--- a/app/jobs/republica_2023_or_later/import_job.rb
+++ b/app/jobs/republica_2023_or_later/import_job.rb
@@ -1,4 +1,5 @@
 require "httparty"
+require "httparty"
 
 module Republica2023OrLater
   class ImportJob < ApplicationJob
@@ -67,7 +68,9 @@ module Republica2023OrLater
             session.starts_at = session_data["datetime_start"]
             session.ends_at = session_data["datetime_end"]
             session.url = "https://re-publica.com#{session_data['path']}"
-            session.speakers = session_data["speaker_uid"].map { |speaker_uid| conference.speakers.find_by!(ref_id: speaker_uid) }
+            session.speakers = session_data["speaker_uid"].map do |speaker_uid|
+              conference.speakers.find_by!(ref_id: speaker_uid)
+            end
             session.save!
           end
         end
diff --git a/app/models/filedrop_file.rb b/app/models/filedrop_file.rb
index af8f3dc..400955b 100644
--- a/app/models/filedrop_file.rb
+++ b/app/models/filedrop_file.rb
@@ -1,6 +1,7 @@
 class FiledropFile < ApplicationRecord
   belongs_to :session
-  validates :checksum, presence: true, format: { with: /\A[0-9a-fA-F]+\z/, message: "only allows hexadecimal characters" }
+  validates :checksum, presence: true,
+                       format: { with: /\A[0-9a-fA-F]+\z/, message: "only allows hexadecimal characters" }
 
   def sanitize_filename(filename)
     filename.gsub(/[^\w\s.-]/, "_")
@@ -9,11 +10,11 @@ class FiledropFile < ApplicationRecord
   def safe_download_path(download_dir, filename)
     sanitized_filename = sanitize_filename(filename)
     output_path = File.join(download_dir, sanitized_filename)
-    if File.expand_path(output_path).start_with?(File.expand_path(download_dir))
-      output_path
-    else
+    unless File.expand_path(output_path).start_with?(File.expand_path(download_dir))
       raise "Invalid filename, potential directory traversal detected!"
     end
+
+    output_path
   end
 
   def download(url)
diff --git a/app/models/session.rb b/app/models/session.rb
index d11923d..8577ddc 100644
--- a/app/models/session.rb
+++ b/app/models/session.rb
@@ -64,8 +64,9 @@ class Session < ApplicationRecord
 
   def notify_if_changed
     return if new_record?
-    if saved_changes.present?
-      ActiveSupport::Notifications.instrument("session.updated", record: self, changes: saved_changes)
-    end
+
+    return unless saved_changes.present?
+
+    ActiveSupport::Notifications.instrument("session.updated", record: self, changes: saved_changes)
   end
 end
diff --git a/app/models/speaker.rb b/app/models/speaker.rb
index de7b9b8..2e1d8ff 100644
--- a/app/models/speaker.rb
+++ b/app/models/speaker.rb
@@ -15,8 +15,9 @@ class Speaker < ApplicationRecord
 
   def notify_if_changed
     return if new_record?
-    if saved_changes.present?
-      ActiveSupport::Notifications.instrument("speaker.updated", record: self, changes: saved_changes)
-    end
+
+    return unless saved_changes.present?
+
+    ActiveSupport::Notifications.instrument("speaker.updated", record: self, changes: saved_changes)
   end
 end
diff --git a/app/subscribers/assignment_audit_subscriber.rb b/app/subscribers/assignment_audit_subscriber.rb
index 4f01df4..4922d51 100644
--- a/app/subscribers/assignment_audit_subscriber.rb
+++ b/app/subscribers/assignment_audit_subscriber.rb
@@ -2,7 +2,7 @@ class AssignmentAuditSubscriber
   def self.subscribe
     ActiveSupport::Notifications.subscribe(/\Aassignment\..*/) do |*args|
       event = ActiveSupport::Notifications::Event.new(*args)
-      new.handle_event(event)  # Call the instance method
+      new.handle_event(event) # Call the instance method
     end
   end
 
diff --git a/app/subscribers/revision_subscriber.rb b/app/subscribers/revision_subscriber.rb
index 92bb52c..e109b53 100644
--- a/app/subscribers/revision_subscriber.rb
+++ b/app/subscribers/revision_subscriber.rb
@@ -2,7 +2,7 @@ class RevisionSubscriber
   def self.subscribe
     ActiveSupport::Notifications.subscribe(/\A(?:session|speaker)\.updated/) do |*args|
       event = ActiveSupport::Notifications::Event.new(*args)
-      new.handle_event(event)  # Call the instance method
+      new.handle_event(event) # Call the instance method
     end
   end
 
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb
index 8834e7c..1289c8d 100644
--- a/app/views/layouts/application.html.erb
+++ b/app/views/layouts/application.html.erb
@@ -1,84 +1,58 @@
 <!DOCTYPE html>
-<html class="md:scroll-pt-16">
+<html>
   <head>
-    <title>ReScheduled</title>
-    <meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
+    <title>re:scheduled</title>
+    <meta name="viewport" content="width=device-width,initial-scale=1">
     <%= csrf_meta_tags %>
     <%= csp_meta_tag %>
-    <%= stylesheet_link_tag "tailwind", "inter-font", "data-turbo-track": "reload" %>
 
-    <%= stylesheet_link_tag "application" %>
+    <%= stylesheet_link_tag "tailwind", "inter-font", "data-turbo-track": "reload" %>
+    <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
     <%= javascript_importmap_tags %>
-
-    <script type="text/javascript">
-      function applyDarkmode() {
-        const userTheme = document.body.dataset.darkmode;
-        document.documentElement.classList.toggle(
-          'dark',
-          userTheme === 'dark' || ((userTheme === 'auto') && window.matchMedia('(prefers-color-scheme: dark)').matches)
-        );
-      }
-      const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
-      mediaQuery.addEventListener('change', applyDarkmode);
-    </script>
   </head>
 
-  <body <%= tag.attributes(body_data_attributes) %> class="dark:bg-gray-900 dark:text-slate-300">
-  <script type="text/javascript">
-    applyDarkmode(); // Required to prevent flashing on load
-  </script>
-  <nav class="bg-slate-100 dark:bg-zinc-700 text-gray-700 dark:text-slate-300 shadow w-full relative md:fixed z-50" data-controller="navigation">
-    <div class="relative bg-slate-100 dark:bg-zinc-700 z-50 container mx-auto px-4 py-4 flex justify-between items-center">
-      <div class="flex items-center space-x-4">
-        <div class="text-xl font-bold text-black dark:text-white"><%= link_to 're:scheduled', '/', class: "!no-underline" %></div>
-        <div class="hidden md:flex space-x-4">
-          <%= link_to 'Conferences', conferences_path, class: 'hover:text-gray-900 dark:hover:text-slate-200' %>
-          <%= link_to 'Assignments', assignments_path, class: 'hover:text-gray-900 dark:hover:text-slate-200' %>
+  <body class="bg-gray-100 dark:bg-gray-900 min-h-screen">
+    <header class="bg-white dark:bg-gray-800 shadow">
+      <div class="container mx-auto px-4 py-4 flex justify-between items-center">
+        <div class="flex items-center">
+          <h1 class="text-xl font-bold text-gray-900 dark:text-white">
+            <%= link_to "re:scheduled", root_path %>
+          </h1>
         </div>
+        <nav class="flex items-center space-x-4">
+          <% if user_signed_in? %>
+            <div class="flex items-center mr-4">
+              <div class="w-8 h-8 rounded-full flex items-center justify-center mr-2" style="background-color: <%= current_user.avatar_color %>; color: <%= current_user.text_color %>">
+                <%= current_user.initials %>
+              </div>
+              <span class="text-gray-700 dark:text-gray-300"><%= current_user.name %></span>
+            </div>
+            <% if current_user.has_role?("events_admin") %>
+              <%= link_to "Admin", admin_conferences_path, class: "text-gray-600 hover:text-gray-900 dark:text-gray-300 dark:hover:text-white" %>
+            <% end %>
+            <%= link_to "Conferences", conferences_path, class: "text-gray-600 hover:text-gray-900 dark:text-gray-300 dark:hover:text-white" %>
+            <%= link_to "Assignments", assignments_path, class: "text-gray-600 hover:text-gray-900 dark:text-gray-300 dark:hover:text-white" %>
+            <%= link_to "Sign Out", destroy_user_session_path, method: :delete, class: "text-gray-600 hover:text-gray-900 dark:text-gray-300 dark:hover:text-white" %>
+          <% else %>
+            <%= link_to "Sign In", new_user_session_path, class: "text-gray-600 hover:text-gray-900 dark:text-gray-300 dark:hover:text-white" %>
+          <% end %>
+        </nav>
       </div>
-      <div class="hidden md:flex items-center space-x-4 ml-0 lg:ml-8">
-        <% if user_signed_in? %>
-        <span class="-mr-2 hidden lg:inline">logged in as</span>
-        <%= render partial: 'application/user_avatar', locals: { user: current_user } %>
-        <%= link_to '<span class="hidden lg:inline">My </span>Profile'.html_safe, edit_user_registration_path, class: 'hover:text-gray-900 dark:hover:text-slate-200', aria_label: "My Profile" %>
-        <%= link_to 'My Assignments', user_assignments_path(current_user), class: 'hover:text-gray-900 dark:hover:text-slate-200' %>
-        <%= link_to 'Logout', destroy_user_session_path, data: { turbo_method: :delete }, class: 'hover:text-gray-900 dark:hover:text-slate-200' %>
-        <% else %>
-        <span class="px-2">not logged in</span>
-        <%= link_to 'Login', new_user_session_path, class: 'hover:text-gray-900 dark:hover:text-slate-200' %>
-        <%= link_to 'Sign Up', new_user_registration_path, class: 'hover:text-gray-900 dark:hover:text-slate-200' %>
-        <% end %>
-      </div>
-      <div class="md:hidden">
-        <button id="menu-button" class="text-gray-700 dark:text-slate-400 hover:text-gray-900 dark:hover:text-white focus:outline-none" data-action="click->navigation#toggleMenu">
-          <svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
-            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
-          </svg>
-        </button>
-      </div>
-    </div>
-    <div id="mobile-menu" class="absolute top-18 bg-slate-100 dark:bg-zinc-700 z-20 container mx-auto hidden md:hidden space-y-4 px-8 pb-4 shadow" data-navigation-target="mobileMenu">
-        <%= link_to 'Conferences', conferences_path, class: 'block hover:text-gray-900 dark:hover:text-white' %>
-        <%= link_to 'Assignments', assignments_path, class: 'block hover:text-gray-900 dark:hover:text-white' %>
-        <hr>
-        <% if user_signed_in? %>
-        <div>logged in as <%= render partial: 'application/user_avatar', locals: { user: current_user } %></div>
-        <%= link_to 'My Profile', edit_user_registration_path, class: 'block hover:text-gray-900 dark:hover:text-white' %>
-        <%= link_to 'My Assignments', user_assignments_path(current_user), class: 'block hover:text-gray-900 dark:hover:text-white' %>
-        <%= link_to 'Logout', destroy_user_session_path, data: { turbo_method: :delete }, class: 'block hover:text-gray-900 dark:hover:text-white' %>
-        <% else %>
-        <div>not logged in</div>
-        <%= link_to 'Login', new_user_session_path, class: 'block hover:text-gray-900 dark:hover:text-white' %>
-        <%= link_to 'Sign Up', new_user_registration_path, class: 'block hover:text-gray-900 dark:hover:text-white  ' %>
-        <% end %>
-    </div>
-  </nav>
+    </header>
 
-
-
-
-    <%= render partial: 'shared/flash' %>
-    <main class="container mx-auto mt-8 px-5 flex pb-4 md:mt-24">
+    <main>
+      <% if notice %>
+        <div class="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded relative mb-4 mx-4 mt-4" role="alert">
+          <span class="block sm:inline"><%= notice %></span>
+        </div>
+      <% end %>
+      
+      <% if alert %>
+        <div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative mb-4 mx-4 mt-4" role="alert">
+          <span class="block sm:inline"><%= alert %></span>
+        </div>
+      <% end %>
+      
       <%= yield %>
     </main>
   </body>
diff --git a/config/environments/development.rb b/config/environments/development.rb
index 29d5eb5..3de265f 100644
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -75,6 +75,8 @@ Rails.application.configure do
   config.action_controller.raise_on_missing_callback_actions = true
 
   config.telegram_default_target = ENV["TELEGRAM_DEFAULT_TARGET"] || "2192297"
+
+  config.solid_queue.logger = ActiveSupport::Logger.new(STDOUT)
 end
 
 Rails.application.routes.default_url_options[:host] = "127.0.0.1"
-- 
GitLab