From eaba8b1c18950120b333a56d657da71e93455b80 Mon Sep 17 00:00:00 2001
From: Teal <git@teal.is>
Date: Mon, 27 May 2024 10:46:18 +0200
Subject: [PATCH] LIVE UPDATES BITCHES

---
 app/channels/session_channel.rb            |  9 +++++++++
 app/controllers/assignments_controller.rb  | 19 ++++++++++++++++++-
 app/javascript/application.js              |  2 +-
 app/javascript/channels/consumer.js        |  6 ++++++
 app/javascript/channels/index.js           |  2 ++
 app/javascript/channels/session_channel.js | 15 +++++++++++++++
 app/models/session.rb                      |  8 ++++----
 app/views/sessions/_session.html.erb       |  3 ++-
 config/importmap.rb                        |  2 ++
 test/channels/session_channel_test.rb      |  8 ++++++++
 10 files changed, 67 insertions(+), 7 deletions(-)
 create mode 100644 app/channels/session_channel.rb
 create mode 100644 app/javascript/channels/consumer.js
 create mode 100644 app/javascript/channels/index.js
 create mode 100644 app/javascript/channels/session_channel.js
 create mode 100644 test/channels/session_channel_test.rb

diff --git a/app/channels/session_channel.rb b/app/channels/session_channel.rb
new file mode 100644
index 0000000..8b46fce
--- /dev/null
+++ b/app/channels/session_channel.rb
@@ -0,0 +1,9 @@
+class SessionChannel < ApplicationCable::Channel
+  def subscribed
+    # stream_from "some_channel"
+  end
+
+  def unsubscribed
+    # Any cleanup needed when channel is unsubscribed
+  end
+end
diff --git a/app/controllers/assignments_controller.rb b/app/controllers/assignments_controller.rb
index a0b4def..f7ab1eb 100644
--- a/app/controllers/assignments_controller.rb
+++ b/app/controllers/assignments_controller.rb
@@ -14,7 +14,12 @@ class AssignmentsController < ApplicationController
     params[:user_id] ||= params[:assignment][:user_id]
     if params[:user_id].nil? or params[:user_id].empty?
       flash.now[:alert] = 'Please select a user to assign.'
-
+      Turbo::StreamsChannel.broadcast_replace_later_to(
+        @session,
+        target: dom_id(@session),
+        partial: "sessions/session",
+        locals: { session: @session }
+      )
       respond_to do |format|
         format.turbo_stream { render turbo_stream: turbo_stream.replace(helpers.dom_id(@session), partial: "sessions/session", locals: { session: @session }), status: :unprocessable_entity }
         format.html { redirect_to conference_session_path(@session.conference, @session), alert: 'Please select a user to assign.' }
@@ -27,6 +32,12 @@ class AssignmentsController < ApplicationController
     @assignment = Assignment.new(user: @user, session: @session)
 
     if @assignment.save
+      Turbo::StreamsChannel.broadcast_replace_later_to(
+        @session,
+        target: helpers.dom_id(@session),
+        partial: "sessions/session",
+        locals: { session: @session }
+      )
       flash.now[:success] = 'User assigned successfully.'
       respond_to do |format|
         format.turbo_stream { render turbo_stream: turbo_stream.replace(helpers.dom_id(@session), partial: "sessions/session", locals: { session: @session }) }
@@ -46,6 +57,12 @@ class AssignmentsController < ApplicationController
     @session = @assignment.session
 
     if @assignment&.destroy
+      Turbo::StreamsChannel.broadcast_replace_later_to(
+        @session,
+        target: helpers.dom_id(@session),
+        partial: "sessions/session",
+        locals: { session: @session }
+      )
       respond_to do |format|
         format.turbo_stream { render turbo_stream: turbo_stream.replace(helpers.dom_id(@session), partial: "sessions/session", locals: { session: @session }) }
         format.html { redirect_to conference_session_path(@session.conference, @session), notice: 'User removed successfully.' }
diff --git a/app/javascript/application.js b/app/javascript/application.js
index 84b06eb..0c66ece 100644
--- a/app/javascript/application.js
+++ b/app/javascript/application.js
@@ -15,4 +15,4 @@ document.addEventListener("turbo:load", function() {
       flashMessage.parentNode.removeChild(flashMessage);
     }, 5000);
   });
-});
\ No newline at end of file
+});import "channels"
diff --git a/app/javascript/channels/consumer.js b/app/javascript/channels/consumer.js
new file mode 100644
index 0000000..8ec3aad
--- /dev/null
+++ b/app/javascript/channels/consumer.js
@@ -0,0 +1,6 @@
+// Action Cable provides the framework to deal with WebSockets in Rails.
+// You can generate new channels where WebSocket features live using the `bin/rails generate channel` command.
+
+import { createConsumer } from "@rails/actioncable"
+
+export default createConsumer()
diff --git a/app/javascript/channels/index.js b/app/javascript/channels/index.js
new file mode 100644
index 0000000..7b67b92
--- /dev/null
+++ b/app/javascript/channels/index.js
@@ -0,0 +1,2 @@
+// Import all the channels to be used by Action Cable
+import "channels/session_channel"
diff --git a/app/javascript/channels/session_channel.js b/app/javascript/channels/session_channel.js
new file mode 100644
index 0000000..7041654
--- /dev/null
+++ b/app/javascript/channels/session_channel.js
@@ -0,0 +1,15 @@
+import consumer from "channels/consumer"
+
+consumer.subscriptions.create("SessionChannel", {
+  connected() {
+    // Called when the subscription is ready for use on the server
+  },
+
+  disconnected() {
+    // Called when the subscription has been terminated by the server
+  },
+
+  received(data) {
+    // Called when there's incoming data on the websocket for this channel
+  }
+});
diff --git a/app/models/session.rb b/app/models/session.rb
index 402c57e..2c718d8 100644
--- a/app/models/session.rb
+++ b/app/models/session.rb
@@ -6,13 +6,13 @@ class Session < ApplicationRecord
   has_many :session_speakers, dependent: :destroy
   has_many :speakers, through: :session_speakers
 
-
   scope :scheduled, -> { where(status: 'scheduled') }
-
+  
   validates :ref_id, uniqueness: { scope: :conference_id }
-
+  
   after_update :notify_if_changed
-
+  after_update_commit -> { broadcast_replace_to "sessions" }
+  
   self.implicit_order_column = :starts_at
 
   def to_param
diff --git a/app/views/sessions/_session.html.erb b/app/views/sessions/_session.html.erb
index 2f2fb48..4a49a8a 100644
--- a/app/views/sessions/_session.html.erb
+++ b/app/views/sessions/_session.html.erb
@@ -1,4 +1,5 @@
-<% unassigned_users = @users - session.assignments.collect(&:user) %>
+<% unassigned_users = User.all - session.assignments.collect(&:user) %>
+<%= turbo_stream_from session %>
 <%= turbo_frame_tag dom_id(session) do %>
   <div class="session shadow hover:shadow-lg overflow-scroll text-sm w-full !h-full min-h-full hover:!min-h-max <%= session.translators_needed? ? "translators-needed" : "no-translators-needed" %> <%= session.backup_needed? ? "backup-needed" : "no-backup-needed" %> <%= session.has_assignees? ? "has-assignees" : "no-assignees" %>">
     <h4>
diff --git a/config/importmap.rb b/config/importmap.rb
index cb0480c..8bebd2c 100644
--- a/config/importmap.rb
+++ b/config/importmap.rb
@@ -5,3 +5,5 @@ pin "@hotwired/stimulus", to: "stimulus.min.js"
 pin "@hotwired/stimulus-loading", to: "stimulus-loading.js"
 pin_all_from "app/javascript/controllers", under: "controllers"
 pin "@hotwired/turbo-rails", to: "turbo.min.js"
+pin "@rails/actioncable", to: "actioncable.esm.js"
+pin_all_from "app/javascript/channels", under: "channels"
diff --git a/test/channels/session_channel_test.rb b/test/channels/session_channel_test.rb
new file mode 100644
index 0000000..f24560b
--- /dev/null
+++ b/test/channels/session_channel_test.rb
@@ -0,0 +1,8 @@
+require "test_helper"
+
+class SessionChannelTest < ActionCable::Channel::TestCase
+  # test "subscribes" do
+  #   subscribe
+  #   assert subscription.confirmed?
+  # end
+end
-- 
GitLab