Skip to content

Commit eb86d37

Browse files
committed
Base implementation of WebSockets
Initial (not-yet-functional) implementation of Action Cable to stream notification counts and new notifications
1 parent 6b03ed7 commit eb86d37

15 files changed

Lines changed: 111 additions & 4 deletions
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,19 @@
11
module ApplicationCable
22
class Connection < ActionCable::Connection::Base
3+
identified_by :current_user
4+
5+
def connect
6+
self.current_user = find_verified_user
7+
end
8+
9+
private
10+
11+
def find_verified_user
12+
if verified_user = env['warden'].user
13+
verified_user
14+
else
15+
reject_unauthorized_connection
16+
end
17+
end
318
end
419
end
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class NotificationCountsChannel < ApplicationCable::Channel
2+
def subscribed
3+
stream_from current_user
4+
end
5+
end
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class WebNotificationsChannel < ApplicationCable::Channel
2+
def subscribed
3+
stream_from current_user
4+
end
5+
end
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Action Cable provides the framework to deal with WebSockets in Rails.
2+
// You can generate new channels where WebSocket features live using the `bin/rails generate channel` command.
3+
4+
import { createConsumer } from "@rails/actioncable"
5+
6+
export default createConsumer()

app/javascript/channels/index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// Load all the channels within this directory and all subdirectories.
2+
// Channel files must be named *_channel.js.
3+
4+
const channels = require.context('.', true, /_channel\.js$/)
5+
channels.keys().forEach(channels)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
2+
import consumer from "./consumer"
3+
4+
consumer.subscriptions.create("NotificationCountsChannel", {
5+
received(data) {
6+
this.badge.html(data["count"] == 0 ? "" : data["count"]);
7+
this.badge.data("count", data["count"]);
8+
},
9+
10+
get badge() {
11+
return $("#notification-count-badge");
12+
}
13+
});
14+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import consumer from "./consumer"
2+
3+
consumer.subscriptions.create("WebNotificationsChannel", {
4+
received(data) {
5+
// TODO
6+
// - authorize
7+
// - broadcast
8+
// - sound
9+
// - remember to use tags!
10+
// new Notification(data["title"], { body: data["body"] })
11+
}
12+
})
13+

app/javascript/packs/application.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,5 @@ import "packs/dictionary";
2828
import "packs/network";
2929
import "packs/styling";
3030
import "packs/copyable";
31+
import "channels/index.js";
3132

app/models/notification.rb

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,13 @@ class Notification < ApplicationRecord
33
belongs_to :notifiable, polymorphic: true
44
belongs_to :linkeable, polymorphic: true, optional: true
55

6-
after_create do
7-
# Send email notification
6+
after_create(:send_email_notification)
7+
after_create(:broadcast_web_notification)
8+
after_save(:broadcast_notification_count)
9+
10+
private
11+
12+
def send_email_notification
813
mail = AdminMailer.with(
914
user: user,
1015
object: notifiable,
@@ -16,4 +21,19 @@ class Notification < ApplicationRecord
1621
update(notified_email: true)
1722
end
1823
end
24+
25+
def broadcast_web_notification
26+
WebNotificationsChannel.broadcast_to(
27+
user,
28+
title: title || action,
29+
tag: notifiable,
30+
alert: id
31+
)
32+
end
33+
34+
def broadcast_notification_count
35+
NotificationCountsChannel.broadcast_to(
36+
user, count: user.unseen_notifications.count
37+
)
38+
end
1939
end

app/views/shared/_user_links.html.erb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
<%= link_to(notifications_path, title: 'Alerts') do %>
2020
<span class="d-lg-none">Notifications</span>
2121
<% if current_user.unseen_notifications.any? %>
22-
<span
22+
<span id="notification-count-badge"
23+
data-count="<%= current_user.unseen_notifications.count %>"
2324
class="nav-item-text badge badge-pill badge-info py-1 px-2 mr-1">
2425
<%= current_user.unseen_notifications.count %>
2526
</span>

0 commit comments

Comments
 (0)