Add an index view for all notifications

This commit is contained in:
Kevin McConnell
2025-01-16 15:26:12 +00:00
parent c4f50fa634
commit 6706802b89
11 changed files with 130 additions and 72 deletions
+63 -63
View File
@@ -2,83 +2,83 @@
height: 4rem;
inset: auto auto var(--block-space);
position: fixed;
}
.notification {
inset: auto auto 0;
position: absolute;
transform: translate(var(--offsetX), var(--offsetY));
transform-origin: center center;
transition: transform 0.2s ease-in-out;
z-index: var(--z-index);
.notification {
inset: auto auto 0;
position: absolute;
transform: translate(var(--offsetX), var(--offsetY));
transform-origin: center center;
transition: transform 0.2s ease-in-out;
z-index: var(--z-index);
.notification__content {
color: var(--color-ink);
inline-size: var(--width);
}
.notification__content {
color: var(--color-ink);
inline-size: var(--width);
}
&:nth-child(1) {
--offsetX: 0;
--offsetY: 0;
--width: 40ch;
--z-index: 0;
}
&:nth-child(2) {
--offsetX: 0.5ch;
--offsetY: calc(var(--block-space-half) * -1);
--width: 39ch;
--z-index: -1;
}
&:nth-child(3) {
--offsetX: 1ch;
--offsetY: calc(var(--block-space) * -1);
--width: 38ch;
--z-index: -2;
}
&:nth-child(4) {
--offsetX: 1.5ch;
--offsetY: calc(var(--block-space) * -1.5);
--width: 37ch;
--z-index: -3;
}
&:nth-child(5) {
--offsetX: 2ch;
--offsetY: calc(var(--block-space) * -2);
--width: 36ch;
--z-index: -4;
}
&:nth-child(1n + 6) {
display: none;
}
.notification-tray:hover & {
&:nth-child(2) {
&:nth-child(1) {
--offsetX: 0;
--offsetY: calc((100% + var(--block-space-half)) * -1);
--offsetY: 0;
--width: 40ch;
--z-index: 0;
}
&:nth-child(2) {
--offsetX: 0.5ch;
--offsetY: calc(var(--block-space-half) * -1);
--width: 39ch;
--z-index: -1;
}
&:nth-child(3) {
--offsetX: 0;
--offsetY: calc((100% + var(--block-space-half)) * -2);
--width: 40ch;
--offsetX: 1ch;
--offsetY: calc(var(--block-space) * -1);
--width: 38ch;
--z-index: -2;
}
&:nth-child(4) {
--offsetX: 0;
--offsetY: calc((100% + var(--block-space-half)) * -3);
--width: 40ch;
--offsetX: 1.5ch;
--offsetY: calc(var(--block-space) * -1.5);
--width: 37ch;
--z-index: -3;
}
&:nth-child(5) {
--offsetX: 0;
--offsetY: calc((100% + var(--block-space-half)) * -4);
--width: 40ch;
--offsetX: 2ch;
--offsetY: calc(var(--block-space) * -2);
--width: 36ch;
--z-index: -4;
}
&:nth-child(1n + 6) {
display: none;
}
.notification-tray:hover & {
&:nth-child(2) {
--offsetX: 0;
--offsetY: calc((100% + var(--block-space-half)) * -1);
--width: 40ch;
}
&:nth-child(3) {
--offsetX: 0;
--offsetY: calc((100% + var(--block-space-half)) * -2);
--width: 40ch;
}
&:nth-child(4) {
--offsetX: 0;
--offsetY: calc((100% + var(--block-space-half)) * -3);
--width: 40ch;
}
&:nth-child(5) {
--offsetX: 0;
--offsetY: calc((100% + var(--block-space-half)) * -4);
--width: 40ch;
}
}
}
}
@@ -0,0 +1,6 @@
class NotificationsController < ApplicationController
def index
@read = Current.user.notifications.read.ordered
@unread = Current.user.notifications.unread.ordered
end
end
+1 -1
View File
@@ -8,6 +8,6 @@ class ReadingsController < ApplicationController
private
def mark_bubble_notifications_read
Current.user.notifications.where(bubble: @bubble).update(read: true)
Current.user.notifications.where(bubble: @bubble).update(read_at: Time.current)
end
end
+7 -2
View File
@@ -4,10 +4,15 @@ class Notification < ApplicationRecord
belongs_to :bubble
belongs_to :resource, polymorphic: true
scope :unread, -> { where(read: false) }
scope :ordered, -> { order(read: :desc, created_at: :desc) }
scope :unread, -> { where(read_at: nil) }
scope :read, -> { where.not(read_at: nil) }
scope :ordered, -> { order(read_at: :desc, created_at: :desc) }
delegate :creator, to: :event
broadcasts_to ->(notification) { [ notification.user, :notifications ] }, inserts_by: :prepend
def read?
read_at.present?
end
end
+2
View File
@@ -7,6 +7,8 @@
<span class="for-screen-reader">Account settings</span>
<% end %>
<%= link_to "All notifications", notifications_path %>
<%= link_to new_bucket_path, class: "btn flex-item-justify-end", style: "view-transition-name: new-bucket" do %>
<%= image_tag "add.svg", aria: { hidden: true }, size: 24 %>
<span class="for-screen-reader">Add a new project</span>
+27
View File
@@ -0,0 +1,27 @@
<% @page_title = "Notifications" %>
<% content_for :header do %>
<nav>
<%= link_to root_path, class: "btn flex-item-justify-start", data: { controller: "hotkey", action: "keydown.esc@document->hotkey#click" } do %>
<%= image_tag "arrow-left.svg", aria: { hidden: true }, size: 24 %>
<span class="for-screen-reader">Go back</span>
<% end %>
<h1>All notifications</h1>
<%= link_to new_bucket_path, class: "btn flex-item-justify-end", style: "view-transition-name: new-bucket" do %>
<%= image_tag "add.svg", aria: { hidden: true }, size: 24 %>
<span class="for-screen-reader">Add a new project</span>
<% end %>
</nav>
<% end %>
<% if @unread.any? %>
<h2>New for you</h2>
<%= render @unread %>
<% end %>
<% if @read.any? %>
<h2>Previously read</h2>
<%= render @read %>
<% end %>
+2 -1
View File
@@ -18,8 +18,9 @@ Rails.application.routes.draw do
end
resources :bubbles
resources :notifications, only: :index
namespace :notifications do
resource :tray
resource :tray, only: :show
end
resources :buckets do
@@ -0,0 +1,12 @@
class ChangeNotificationReadToReadAt < ActiveRecord::Migration[8.1]
def change
remove_index :notifications, %i[ user_id read created_at ], order: { read: :desc, created_at: :desc }
change_table :notifications do |t|
t.remove :read
t.datetime :read_at
t.index %i[ user_id read_at created_at ], order: { read_at: :desc, created_at: :desc }
end
end
end
Generated
+3 -3
View File
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[8.1].define(version: 2025_01_15_122810) do
ActiveRecord::Schema[8.1].define(version: 2025_01_16_163344) do
create_table "accesses", force: :cascade do |t|
t.integer "bucket_id", null: false
t.integer "user_id", null: false
@@ -183,13 +183,13 @@ ActiveRecord::Schema[8.1].define(version: 2025_01_15_122810) do
t.integer "bubble_id", null: false
t.string "resource_type", null: false
t.integer "resource_id", null: false
t.boolean "read", default: false, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.datetime "read_at"
t.index ["bubble_id"], name: "index_notifications_on_bubble_id"
t.index ["event_id"], name: "index_notifications_on_event_id"
t.index ["resource_type", "resource_id"], name: "index_notifications_on_resource"
t.index ["user_id", "read", "created_at"], name: "index_notifications_on_user_id_and_read_and_created_at", order: { read: :desc, created_at: :desc }
t.index ["user_id", "read_at", "created_at"], name: "index_notifications_on_user_id_and_read_at_and_created_at", order: { read_at: :desc, created_at: :desc }
t.index ["user_id"], name: "index_notifications_on_user_id"
end
@@ -0,0 +1,7 @@
require "test_helper"
class NotificationsControllerTest < ActionDispatch::IntegrationTest
# test "the truth" do
# assert true
# end
end
-2
View File
@@ -3,7 +3,6 @@ logo_published_kevin:
event: logo_published
bubble: logo
resource: logo (Bubble)
read: false
created_at: <%= 1.week.ago %>
layout_commented_kevin:
@@ -11,5 +10,4 @@ layout_commented_kevin:
event: layout_commented
bubble: layout
resource: layout_overflowing_david (Comment)
read: false
created_at: <%= 1.week.ago %>