From c4f50fa63488b61887c68ec7954c698d0b3b5a8a Mon Sep 17 00:00:00 2001 From: Kevin McConnell Date: Thu, 16 Jan 2025 15:07:47 +0000 Subject: [PATCH 01/15] Move notifications to tray controller --- .../trays_controller.rb} | 4 ++-- app/views/notifications/_tray.html.erb | 2 +- app/views/notifications/index.html.erb | 3 --- app/views/notifications/trays/show.html.erb | 3 +++ config/routes.rb | 4 +++- .../trays_controller_test.rb} | 6 +++--- 6 files changed, 12 insertions(+), 10 deletions(-) rename app/controllers/{notifications_controller.rb => notifications/trays_controller.rb} (53%) delete mode 100644 app/views/notifications/index.html.erb create mode 100644 app/views/notifications/trays/show.html.erb rename test/controllers/{notifications_controller_test.rb => notifications/trays_controller_test.rb} (55%) diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications/trays_controller.rb similarity index 53% rename from app/controllers/notifications_controller.rb rename to app/controllers/notifications/trays_controller.rb index 22e40167e..4a01a1ee9 100644 --- a/app/controllers/notifications_controller.rb +++ b/app/controllers/notifications/trays_controller.rb @@ -1,5 +1,5 @@ -class NotificationsController < ApplicationController - def index +class Notifications::TraysController < ApplicationController + def show @notifications = Current.user.notifications.unread.ordered.limit(20) end end diff --git a/app/views/notifications/_tray.html.erb b/app/views/notifications/_tray.html.erb index 71ada65cb..af4385822 100644 --- a/app/views/notifications/_tray.html.erb +++ b/app/views/notifications/_tray.html.erb @@ -1,5 +1,5 @@ <%= turbo_stream_from Current.user, :notifications %> <%= tag.div id: "notification-tray", class: "notification-tray flex flex-column gap", data: { turbo_permanent: true } do %> - <%= turbo_frame_tag("notifications", src: notifications_path) %> + <%= turbo_frame_tag("notifications", src: notifications_tray_path) %> <% end %> diff --git a/app/views/notifications/index.html.erb b/app/views/notifications/index.html.erb deleted file mode 100644 index ee91b07e4..000000000 --- a/app/views/notifications/index.html.erb +++ /dev/null @@ -1,3 +0,0 @@ -<%= turbo_frame_tag "notifications" do %> - <%= render @notifications %> -<% end %> diff --git a/app/views/notifications/trays/show.html.erb b/app/views/notifications/trays/show.html.erb new file mode 100644 index 000000000..051055670 --- /dev/null +++ b/app/views/notifications/trays/show.html.erb @@ -0,0 +1,3 @@ +<%= turbo_frame_tag "notifications" do %> + <%= render collection: @notifications, partial: "notifications/notification" %> +<% end %> diff --git a/config/routes.rb b/config/routes.rb index f122bb209..92fcc6806 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -18,7 +18,9 @@ Rails.application.routes.draw do end resources :bubbles - resources :notifications + namespace :notifications do + resource :tray + end resources :buckets do resources :bubbles do diff --git a/test/controllers/notifications_controller_test.rb b/test/controllers/notifications/trays_controller_test.rb similarity index 55% rename from test/controllers/notifications_controller_test.rb rename to test/controllers/notifications/trays_controller_test.rb index fc4c2bfee..7d44a3e00 100644 --- a/test/controllers/notifications_controller_test.rb +++ b/test/controllers/notifications/trays_controller_test.rb @@ -1,12 +1,12 @@ require "test_helper" -class NotificationsControllerTest < ActionDispatch::IntegrationTest +class Notifications::TraysControllerTest < ActionDispatch::IntegrationTest setup do sign_in_as :kevin end - test "index" do - get notifications_url + test "show" do + get notifications_tray_url assert_response :success assert_select "div", text: /Layout is broken/ From 6706802b89eca551ce49f072b08b8abf0fcaf933 Mon Sep 17 00:00:00 2001 From: Kevin McConnell Date: Thu, 16 Jan 2025 15:26:12 +0000 Subject: [PATCH 02/15] Add an index view for all notifications --- app/assets/stylesheets/notifications.css | 126 +++++++++--------- app/controllers/notifications_controller.rb | 6 + app/controllers/readings_controller.rb | 2 +- app/models/notification.rb | 9 +- app/views/buckets/index.html.erb | 2 + app/views/notifications/index.html.erb | 27 ++++ config/routes.rb | 3 +- ...344_change_notification_read_to_read_at.rb | 12 ++ db/schema.rb | 6 +- .../notifications_controller_test.rb | 7 + test/fixtures/notifications.yml | 2 - 11 files changed, 130 insertions(+), 72 deletions(-) create mode 100644 app/controllers/notifications_controller.rb create mode 100644 app/views/notifications/index.html.erb create mode 100644 db/migrate/20250116163344_change_notification_read_to_read_at.rb create mode 100644 test/controllers/notifications_controller_test.rb diff --git a/app/assets/stylesheets/notifications.css b/app/assets/stylesheets/notifications.css index 4b58106a9..0bcba7d3a 100644 --- a/app/assets/stylesheets/notifications.css +++ b/app/assets/stylesheets/notifications.css @@ -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; + } } } } diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb new file mode 100644 index 000000000..85b656c4c --- /dev/null +++ b/app/controllers/notifications_controller.rb @@ -0,0 +1,6 @@ +class NotificationsController < ApplicationController + def index + @read = Current.user.notifications.read.ordered + @unread = Current.user.notifications.unread.ordered + end +end diff --git a/app/controllers/readings_controller.rb b/app/controllers/readings_controller.rb index 9c5798ed3..1bf106efd 100644 --- a/app/controllers/readings_controller.rb +++ b/app/controllers/readings_controller.rb @@ -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 diff --git a/app/models/notification.rb b/app/models/notification.rb index 531be12bb..da1cc9614 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -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 diff --git a/app/views/buckets/index.html.erb b/app/views/buckets/index.html.erb index 7c2f59a91..baf1e0ddd 100644 --- a/app/views/buckets/index.html.erb +++ b/app/views/buckets/index.html.erb @@ -7,6 +7,8 @@ Account settings <% 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 %> Add a new project diff --git a/app/views/notifications/index.html.erb b/app/views/notifications/index.html.erb new file mode 100644 index 000000000..84e2b4254 --- /dev/null +++ b/app/views/notifications/index.html.erb @@ -0,0 +1,27 @@ +<% @page_title = "Notifications" %> + +<% content_for :header do %> + +<% end %> + +<% if @unread.any? %> +

New for you

+ <%= render @unread %> +<% end %> + +<% if @read.any? %> +

Previously read

+<%= render @read %> +<% end %> diff --git a/config/routes.rb b/config/routes.rb index 92fcc6806..6860a6cf0 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -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 diff --git a/db/migrate/20250116163344_change_notification_read_to_read_at.rb b/db/migrate/20250116163344_change_notification_read_to_read_at.rb new file mode 100644 index 000000000..c9bd6bf64 --- /dev/null +++ b/db/migrate/20250116163344_change_notification_read_to_read_at.rb @@ -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 diff --git a/db/schema.rb b/db/schema.rb index a11bb2a66..e1b644f2d 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -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 diff --git a/test/controllers/notifications_controller_test.rb b/test/controllers/notifications_controller_test.rb new file mode 100644 index 000000000..20b28201d --- /dev/null +++ b/test/controllers/notifications_controller_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class NotificationsControllerTest < ActionDispatch::IntegrationTest + # test "the truth" do + # assert true + # end +end diff --git a/test/fixtures/notifications.yml b/test/fixtures/notifications.yml index 89a8256ee..7bff2665c 100644 --- a/test/fixtures/notifications.yml +++ b/test/fixtures/notifications.yml @@ -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 %> From cb6651e2a71ce93a1dc6a568e606c6213badf690 Mon Sep 17 00:00:00 2001 From: Jason Zimdars Date: Fri, 17 Jan 2025 12:42:46 -0600 Subject: [PATCH 03/15] Style notifications index; add truncation for long notifications --- app/assets/stylesheets/notifications.css | 35 +++++++++++-------- .../notifications/_notification.html.erb | 6 ++-- app/views/notifications/index.html.erb | 16 ++++++--- 3 files changed, 34 insertions(+), 23 deletions(-) diff --git a/app/assets/stylesheets/notifications.css b/app/assets/stylesheets/notifications.css index 0bcba7d3a..6c8c1b355 100644 --- a/app/assets/stylesheets/notifications.css +++ b/app/assets/stylesheets/notifications.css @@ -1,7 +1,7 @@ .notification-tray { - height: 4rem; inset: auto auto var(--block-space); position: fixed; + z-index: 1; .notification { inset: auto auto 0; @@ -11,43 +11,38 @@ transition: transform 0.2s ease-in-out; z-index: var(--z-index); - .notification__content { - color: var(--color-ink); - inline-size: var(--width); - } - &:nth-child(1) { --offsetX: 0; --offsetY: 0; - --width: 40ch; + --width: 38ch; --z-index: 0; } &:nth-child(2) { --offsetX: 0.5ch; --offsetY: calc(var(--block-space-half) * -1); - --width: 39ch; + --width: 37ch; --z-index: -1; } &:nth-child(3) { --offsetX: 1ch; --offsetY: calc(var(--block-space) * -1); - --width: 38ch; + --width: 36ch; --z-index: -2; } &:nth-child(4) { --offsetX: 1.5ch; --offsetY: calc(var(--block-space) * -1.5); - --width: 37ch; + --width: 35ch; --z-index: -3; } &:nth-child(5) { --offsetX: 2ch; --offsetY: calc(var(--block-space) * -2); - --width: 36ch; + --width: 34ch; --z-index: -4; } @@ -59,26 +54,36 @@ &:nth-child(2) { --offsetX: 0; --offsetY: calc((100% + var(--block-space-half)) * -1); - --width: 40ch; + --width: 38ch; } &:nth-child(3) { --offsetX: 0; --offsetY: calc((100% + var(--block-space-half)) * -2); - --width: 40ch; + --width: 38ch; } &:nth-child(4) { --offsetX: 0; --offsetY: calc((100% + var(--block-space-half)) * -3); - --width: 40ch; + --width: 38ch; } &:nth-child(5) { --offsetX: 0; --offsetY: calc((100% + var(--block-space-half)) * -4); - --width: 40ch; + --width: 38ch; } } } } + +.notification__content { + color: var(--color-ink); + inline-size: var(--width, auto); + + .notificiations-list--read & { + border: 1px solid var(--color-subtle); + box-shadow: none; + } +} diff --git a/app/views/notifications/_notification.html.erb b/app/views/notifications/_notification.html.erb index cba5a252f..40506ebb3 100644 --- a/app/views/notifications/_notification.html.erb +++ b/app/views/notifications/_notification.html.erb @@ -5,9 +5,9 @@ <%= avatar_image_tag(notification.creator) %> -
- <%= notification_title(notification) %> -
<%= notification_body(notification) %> · <%= local_datetime_tag(notification.created_at, style: :ago) %>
+
+ <%= notification_title(notification) %> +
<%= notification_body(notification) %> · <%= local_datetime_tag(notification.created_at, style: :ago) %>
<% end %> diff --git a/app/views/notifications/index.html.erb b/app/views/notifications/index.html.erb index 84e2b4254..aed1aa3b7 100644 --- a/app/views/notifications/index.html.erb +++ b/app/views/notifications/index.html.erb @@ -7,7 +7,9 @@ Go back <% end %> -

All notifications

+
+

<%= @page_title %>

+
<%= 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 %> @@ -17,11 +19,15 @@ <% end %> <% if @unread.any? %> -

New for you

- <%= render @unread %> +
+

New for you

+ <%= render @unread %> +
<% end %> <% if @read.any? %> -

Previously read

-<%= render @read %> +
+

Previously seen

+ <%= render @read %> +
<% end %> From be14a910bafeefb9b296509d0f8a7e43a2b84a34 Mon Sep 17 00:00:00 2001 From: Jason Zimdars Date: Fri, 17 Jan 2025 13:06:41 -0600 Subject: [PATCH 04/15] Needed when truncating so the avatar isn't squished --- app/views/notifications/_notification.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/notifications/_notification.html.erb b/app/views/notifications/_notification.html.erb index 40506ebb3..f7414d64c 100644 --- a/app/views/notifications/_notification.html.erb +++ b/app/views/notifications/_notification.html.erb @@ -1,7 +1,7 @@ <% cache notification do %> <%= notification_tag notification do %>
-
+
<%= avatar_image_tag(notification.creator) %>
From 6b832876a2b9957aadf632896b6d368eed8dc0d7 Mon Sep 17 00:00:00 2001 From: Jason Zimdars Date: Fri, 17 Jan 2025 15:30:33 -0600 Subject: [PATCH 05/15] Add a notifications button to the tray for reaching the index when you have no unreads --- app/assets/images/bell.svg | 1 + app/assets/stylesheets/notifications.css | 12 ++++++------ app/views/buckets/index.html.erb | 2 -- app/views/notifications/_tray.html.erb | 5 +++++ 4 files changed, 12 insertions(+), 8 deletions(-) create mode 100644 app/assets/images/bell.svg diff --git a/app/assets/images/bell.svg b/app/assets/images/bell.svg new file mode 100644 index 000000000..52a5611fb --- /dev/null +++ b/app/assets/images/bell.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/stylesheets/notifications.css b/app/assets/stylesheets/notifications.css index 6c8c1b355..a3d66f171 100644 --- a/app/assets/stylesheets/notifications.css +++ b/app/assets/stylesheets/notifications.css @@ -1,5 +1,5 @@ .notification-tray { - inset: auto auto var(--block-space); + inset: auto auto var(--block-space) var(--inline-space); position: fixed; z-index: 1; @@ -15,35 +15,35 @@ --offsetX: 0; --offsetY: 0; --width: 38ch; - --z-index: 0; + --z-index: 1; } &:nth-child(2) { --offsetX: 0.5ch; --offsetY: calc(var(--block-space-half) * -1); --width: 37ch; - --z-index: -1; + --z-index: 0; } &:nth-child(3) { --offsetX: 1ch; --offsetY: calc(var(--block-space) * -1); --width: 36ch; - --z-index: -2; + --z-index: -1; } &:nth-child(4) { --offsetX: 1.5ch; --offsetY: calc(var(--block-space) * -1.5); --width: 35ch; - --z-index: -3; + --z-index: -2; } &:nth-child(5) { --offsetX: 2ch; --offsetY: calc(var(--block-space) * -2); --width: 34ch; - --z-index: -4; + --z-index: -3; } &:nth-child(1n + 6) { diff --git a/app/views/buckets/index.html.erb b/app/views/buckets/index.html.erb index baf1e0ddd..7c2f59a91 100644 --- a/app/views/buckets/index.html.erb +++ b/app/views/buckets/index.html.erb @@ -7,8 +7,6 @@ Account settings <% 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 %> Add a new project diff --git a/app/views/notifications/_tray.html.erb b/app/views/notifications/_tray.html.erb index af4385822..8a781deba 100644 --- a/app/views/notifications/_tray.html.erb +++ b/app/views/notifications/_tray.html.erb @@ -2,4 +2,9 @@ <%= tag.div id: "notification-tray", class: "notification-tray flex flex-column gap", data: { turbo_permanent: true } do %> <%= turbo_frame_tag("notifications", src: notifications_tray_path) %> + + <%= link_to notifications_path, class: "btn flex-item-justify-start" do %> + <%= image_tag "bell.svg", aria: { hidden: true }, size: 24 %> + See all notifications + <% end %> <% end %> From 00e905dd288952a3c4e727ccd01e1811c803285a Mon Sep 17 00:00:00 2001 From: Jason Zimdars Date: Fri, 17 Jan 2025 15:37:43 -0600 Subject: [PATCH 06/15] `New for you` empty state --- app/assets/stylesheets/utilities.css | 4 ++-- app/views/notifications/index.html.erb | 12 ++++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/app/assets/stylesheets/utilities.css b/app/assets/stylesheets/utilities.css index 761a24b5d..17d5747dd 100644 --- a/app/assets/stylesheets/utilities.css +++ b/app/assets/stylesheets/utilities.css @@ -168,8 +168,8 @@ .translucent { opacity: var(--opacity, 0.5); } /* Borders */ -.border { border: var(--border-size, 1px) solid var(--border-color, var(--color-subtle)); } -.border-top { border-top: var(--border-size, 1px) solid var(--border-color, var(--color-subtle)); } +.border { border: var(--border-size, 1px) var(--border-style, solid) var(--border-color, var(--color-subtle)); } +.border-top { border-top: var(--border-size, 1px) var(--border-style, solid) var(--border-color, var(--color-subtle)); } .borderless { border: 0; } /* Border radius */ diff --git a/app/views/notifications/index.html.erb b/app/views/notifications/index.html.erb index aed1aa3b7..efbb8c4e9 100644 --- a/app/views/notifications/index.html.erb +++ b/app/views/notifications/index.html.erb @@ -18,12 +18,16 @@ <% end %> -<% if @unread.any? %> -
+
+ <% if @unread.any? %>

New for you

<%= render @unread %> -
-<% end %> + <% else %> +
+ Nothing new for you. +
+ <% end %> +
<% if @read.any? %>
From cd22046efe51e303b4106912f16c2048ed9efb1c Mon Sep 17 00:00:00 2001 From: Jason Zimdars Date: Sun, 19 Jan 2025 22:27:02 -0600 Subject: [PATCH 07/15] Refactor --- app/assets/stylesheets/notifications.css | 86 ++++++------------------ 1 file changed, 21 insertions(+), 65 deletions(-) diff --git a/app/assets/stylesheets/notifications.css b/app/assets/stylesheets/notifications.css index a3d66f171..959c4592a 100644 --- a/app/assets/stylesheets/notifications.css +++ b/app/assets/stylesheets/notifications.css @@ -1,79 +1,35 @@ .notification-tray { - inset: auto auto var(--block-space) var(--inline-space); + inset: auto auto var(--block-space-double) var(--inline-space); position: fixed; z-index: 1; .notification { + --position: 1; + --scale: calc(1 - var(--position) / 30); + --offset: calc((var(--position) - 1) * -1rem); + --z: calc(5 - var(--position)); + inset: auto auto 0; + inline-size: 38ch; position: absolute; - transform: translate(var(--offsetX), var(--offsetY)); - transform-origin: center center; - transition: transform 0.2s ease-in-out; - z-index: var(--z-index); + scale: var(--scale); + transform: translateY(var(--offset)); + transform-origin: center; + transition: scale 0.2s ease-out, transform 0.2s ease-out; + z-index: var(--z); - &:nth-child(1) { - --offsetX: 0; - --offsetY: 0; - --width: 38ch; - --z-index: 1; - } + &:nth-child(1) { --position: 0; } + &:nth-child(2) { --position: 1; } + &:nth-child(3) { --position: 2; } + &:nth-child(4) { --position: 3; } + &:nth-child(5) { --position: 4; } + &:nth-child(6) { --position: 5; } - &:nth-child(2) { - --offsetX: 0.5ch; - --offsetY: calc(var(--block-space-half) * -1); - --width: 37ch; - --z-index: 0; - } - - &:nth-child(3) { - --offsetX: 1ch; - --offsetY: calc(var(--block-space) * -1); - --width: 36ch; - --z-index: -1; - } - - &:nth-child(4) { - --offsetX: 1.5ch; - --offsetY: calc(var(--block-space) * -1.5); - --width: 35ch; - --z-index: -2; - } - - &:nth-child(5) { - --offsetX: 2ch; - --offsetY: calc(var(--block-space) * -2); - --width: 34ch; - --z-index: -3; - } - - &:nth-child(1n + 6) { - display: none; - } + &:nth-child(1n + 7) { display: none; } .notification-tray:hover & { - &:nth-child(2) { - --offsetX: 0; - --offsetY: calc((100% + var(--block-space-half)) * -1); - --width: 38ch; - } - - &:nth-child(3) { - --offsetX: 0; - --offsetY: calc((100% + var(--block-space-half)) * -2); - --width: 38ch; - } - - &:nth-child(4) { - --offsetX: 0; - --offsetY: calc((100% + var(--block-space-half)) * -3); - --width: 38ch; - } - - &:nth-child(5) { - --offsetX: 0; - --offsetY: calc((100% + var(--block-space-half)) * -4); - --width: 38ch; - } + --scale: 1; + --offset: calc((100% + var(--block-space-half)) * (var(--position) * -1)); } } } From 536dfa65d758e30ff8c85155102046a23ef23fd9 Mon Sep 17 00:00:00 2001 From: Jason Zimdars Date: Mon, 20 Jan 2025 13:00:56 -0600 Subject: [PATCH 08/15] Open tray on click, stub mark-as-read button --- app/assets/stylesheets/notifications.css | 43 +++++++++++++++++------- app/views/notifications/_tray.html.erb | 21 +++++++++--- 2 files changed, 47 insertions(+), 17 deletions(-) diff --git a/app/assets/stylesheets/notifications.css b/app/assets/stylesheets/notifications.css index 959c4592a..a6789dea0 100644 --- a/app/assets/stylesheets/notifications.css +++ b/app/assets/stylesheets/notifications.css @@ -1,16 +1,21 @@ .notification-tray { - inset: auto auto var(--block-space-double) var(--inline-space); + --size: 38ch; + + inline-size: var(--size); + inset: auto auto var(--block-space) var(--inline-space); position: fixed; z-index: 1; .notification { + --outline-color: var(--color-link); + --offset: calc((var(--position) - 1) * (var(--block-space) * -1)); --position: 1; --scale: calc(1 - var(--position) / 30); - --offset: calc((var(--position) - 1) * -1rem); - --z: calc(5 - var(--position)); + --z: calc(6 - var(--position)); inset: auto auto 0; - inline-size: 38ch; + inline-size: var(--size); + pointer-events: none; position: absolute; scale: var(--scale); transform: translateY(var(--offset)); @@ -18,28 +23,42 @@ transition: scale 0.2s ease-out, transform 0.2s ease-out; z-index: var(--z); - &:nth-child(1) { --position: 0; } - &:nth-child(2) { --position: 1; } - &:nth-child(3) { --position: 2; } - &:nth-child(4) { --position: 3; } - &:nth-child(5) { --position: 4; } - &:nth-child(6) { --position: 5; } + &:nth-child(1) { --position: 1; } + &:nth-child(2) { --position: 2; } + &:nth-child(3) { --position: 3; } + &:nth-child(4) { --position: 4; } + &:nth-child(5) { --position: 5; } + &:nth-child(6) { --position: 6; } &:nth-child(1n + 7) { display: none; } - .notification-tray:hover & { + .notification-tray[open] & { --scale: 1; --offset: calc((100% + var(--block-space-half)) * (var(--position) * -1)); + pointer-events: unset; } } } .notification__content { color: var(--color-ink); - inline-size: var(--width, auto); .notificiations-list--read & { border: 1px solid var(--color-subtle); box-shadow: none; } } + +.notification-tray__expander { + --hover-size: 0; + --outline-size: 0; + + cursor: pointer; + inset: 0; + position: absolute; + z-index: 6; + + .notification-tray[open] & { + display: none; + } +} diff --git a/app/views/notifications/_tray.html.erb b/app/views/notifications/_tray.html.erb index 8a781deba..6e2356f5e 100644 --- a/app/views/notifications/_tray.html.erb +++ b/app/views/notifications/_tray.html.erb @@ -1,10 +1,21 @@ <%= turbo_stream_from Current.user, :notifications %> -<%= tag.div id: "notification-tray", class: "notification-tray flex flex-column gap", data: { turbo_permanent: true } do %> +<%= tag.dialog id: "notification-tray", class: "notification-tray flex flex-column gap unpad borderless", + data: { controller: "dialog", turbo_permanent: true, dialog_modal_value: false, dialog_target: "dialog", action: "keydown.esc@document->dialog#close click@document->dialog#closeOnClickOutside" } do %> <%= turbo_frame_tag("notifications", src: notifications_tray_path) %> - <%= link_to notifications_path, class: "btn flex-item-justify-start" do %> - <%= image_tag "bell.svg", aria: { hidden: true }, size: 24 %> - See all notifications - <% end %> +
+ <%= link_to notifications_path, class: "btn" do %> + <%= image_tag "bell.svg", aria: { hidden: true }, size: 24 %> + See all notifications + <% end %> + + +
+ + <% end %> From 69e235b0820480c97c9ba299d816ffe266272ee9 Mon Sep 17 00:00:00 2001 From: Jason Zimdars Date: Mon, 20 Jan 2025 15:32:34 -0600 Subject: [PATCH 09/15] Move to right side, smooth transition --- app/assets/stylesheets/notifications.css | 19 ++++++++++++++++++- app/views/notifications/_tray.html.erb | 13 ++++++------- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/app/assets/stylesheets/notifications.css b/app/assets/stylesheets/notifications.css index a6789dea0..847d1fc5e 100644 --- a/app/assets/stylesheets/notifications.css +++ b/app/assets/stylesheets/notifications.css @@ -1,8 +1,10 @@ .notification-tray { --size: 38ch; + block-size: calc(4ch + var(--block-space-double)); inline-size: var(--size); - inset: auto auto var(--block-space) var(--inline-space); + inset: auto var(--inline-space) var(--block-space-half) auto; + padding: var(--block-space-half) var(--inline-space); position: fixed; z-index: 1; @@ -35,11 +37,26 @@ .notification-tray[open] & { --scale: 1; --offset: calc((100% + var(--block-space-half)) * (var(--position) * -1)); + + margin-block-end: calc(var(--block-space) * -1); pointer-events: unset; } } } +.notification-tray__actions { + opacity: 0; + scale: calc(1 - 1 / 30); + transform: translateY(100%); + transition: opacity 0.2s ease-out, scale 0.2s ease-out, transform 0.2s ease-out; + + .notification-tray[open] & { + opacity: 1; + scale: 1; + transform: translateY(0); + } +} + .notification__content { color: var(--color-ink); diff --git a/app/views/notifications/_tray.html.erb b/app/views/notifications/_tray.html.erb index 6e2356f5e..86c0cc9f5 100644 --- a/app/views/notifications/_tray.html.erb +++ b/app/views/notifications/_tray.html.erb @@ -1,21 +1,20 @@ <%= turbo_stream_from Current.user, :notifications %> -<%= tag.dialog id: "notification-tray", class: "notification-tray flex flex-column gap unpad borderless", +<%= tag.dialog id: "notification-tray", class: "notification-tray flex flex-column gap unpad borderless justify-end", data: { controller: "dialog", turbo_permanent: true, dialog_modal_value: false, dialog_target: "dialog", action: "keydown.esc@document->dialog#close click@document->dialog#closeOnClickOutside" } do %> <%= turbo_frame_tag("notifications", src: notifications_tray_path) %> -
+
+ + <%= link_to notifications_path, class: "btn" do %> <%= image_tag "bell.svg", aria: { hidden: true }, size: 24 %> See all notifications <% end %> - -
<% end %> From 02573b6dc895baadf4902fbea0f855ff92deb95d Mon Sep 17 00:00:00 2001 From: Jason Zimdars Date: Mon, 20 Jan 2025 17:58:56 -0600 Subject: [PATCH 10/15] Set state for when there are no new notifications --- app/assets/stylesheets/notifications.css | 39 ++++++++++++++++++- .../controllers/dialog_controller.js | 1 + app/views/notifications/_tray.html.erb | 15 ++++--- 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/app/assets/stylesheets/notifications.css b/app/assets/stylesheets/notifications.css index 847d1fc5e..21bf884ce 100644 --- a/app/assets/stylesheets/notifications.css +++ b/app/assets/stylesheets/notifications.css @@ -55,6 +55,42 @@ scale: 1; transform: translateY(0); } + + .notification-tray:has(.notification) & { + .btn img { + display: none; + } + } + + .notification-tray:not(:has(.notification)) & { + opacity: 1; + scale: 1; + transform: none; + transition: none; + + .notification-tray__all_action { + --btn-border-radius: 50%; + --btn-padding: 0; + + aspect-ratio: 1; + block-size: var(--btn-size); + display: grid; + inline-size: var(--btn-size); + place-items: center; + + > * { + grid-area: 1/1; + } + + span { + display: none; + } + } + + .notification-tray__read_action { + display: none; + } + } } .notification__content { @@ -75,7 +111,8 @@ position: absolute; z-index: 6; - .notification-tray[open] & { + .notification-tray[open] &, + .notification-tray:not(:has(.notification)) & { display: none; } } diff --git a/app/javascript/controllers/dialog_controller.js b/app/javascript/controllers/dialog_controller.js index dcea9bdf9..fd4d122e0 100644 --- a/app/javascript/controllers/dialog_controller.js +++ b/app/javascript/controllers/dialog_controller.js @@ -26,6 +26,7 @@ export default class extends Controller { close() { this.dialogTarget.close() + this.dialogTarget.blur() } closeOnClickOutside({ target }) { diff --git a/app/views/notifications/_tray.html.erb b/app/views/notifications/_tray.html.erb index 86c0cc9f5..fa4c650b4 100644 --- a/app/views/notifications/_tray.html.erb +++ b/app/views/notifications/_tray.html.erb @@ -1,20 +1,19 @@ <%= turbo_stream_from Current.user, :notifications %> -<%= tag.dialog id: "notification-tray", class: "notification-tray flex flex-column gap unpad borderless justify-end", - data: { controller: "dialog", turbo_permanent: true, dialog_modal_value: false, dialog_target: "dialog", action: "keydown.esc@document->dialog#close click@document->dialog#closeOnClickOutside" } do %> - <%= turbo_frame_tag("notifications", src: notifications_tray_path) %> - -
- - <%= link_to notifications_path, class: "btn" do %> + <%= link_to notifications_path, class: "notification-tray__all_action btn flex-item-justify-end" do %> <%= image_tag "bell.svg", aria: { hidden: true }, size: 24 %> See all notifications <% end %>
- <% end %> From 404c420a58cb8d8f6aa4d1e1eb01b1487de8c5f1 Mon Sep 17 00:00:00 2001 From: Jason Zimdars Date: Mon, 20 Jan 2025 18:20:58 -0600 Subject: [PATCH 11/15] Add unread dot --- app/assets/stylesheets/notifications.css | 18 ++++++++++++++++++ app/views/notifications/_notification.html.erb | 6 +++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/app/assets/stylesheets/notifications.css b/app/assets/stylesheets/notifications.css index 21bf884ce..a41f36635 100644 --- a/app/assets/stylesheets/notifications.css +++ b/app/assets/stylesheets/notifications.css @@ -116,3 +116,21 @@ display: none; } } + +.notification__unread_indicator { + --size: 0.8em; + + padding-block-start: var(--size); + + .dot { + aspect-ratio: 1; + background-color: var(--color-marker); + border-radius: 50%; + block-size: var(--size); + inline-size: var(--size); + } + + .notificiations-list--read & { + display: none; + } +} diff --git a/app/views/notifications/_notification.html.erb b/app/views/notifications/_notification.html.erb index f7414d64c..d309015b3 100644 --- a/app/views/notifications/_notification.html.erb +++ b/app/views/notifications/_notification.html.erb @@ -5,10 +5,14 @@ <%= avatar_image_tag(notification.creator) %>
-
+
<%= notification_title(notification) %>
<%= notification_body(notification) %> · <%= local_datetime_tag(notification.created_at, style: :ago) %>
+ +
+
+
<% end %> <% end %> From 5d5dc8fb730e9ee60575ef756696372f74bc7006 Mon Sep 17 00:00:00 2001 From: Kevin McConnell Date: Tue, 21 Jan 2025 13:56:53 +0000 Subject: [PATCH 12/15] Wire up notifications "Mark all as read" button --- .../notifications/mark_all_reads_controller.rb | 5 +++++ app/controllers/readings_controller.rb | 2 +- app/models/notification.rb | 6 ++++++ app/views/notifications/_tray.html.erb | 4 ++-- .../mark_all_reads/create.html.erb | 1 + config/routes.rb | 1 + .../mark_all_reads_controller_test.rb | 17 +++++++++++++++++ 7 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 app/controllers/notifications/mark_all_reads_controller.rb create mode 100644 app/views/notifications/mark_all_reads/create.html.erb create mode 100644 test/controllers/notifications/mark_all_reads_controller_test.rb diff --git a/app/controllers/notifications/mark_all_reads_controller.rb b/app/controllers/notifications/mark_all_reads_controller.rb new file mode 100644 index 000000000..2aad42028 --- /dev/null +++ b/app/controllers/notifications/mark_all_reads_controller.rb @@ -0,0 +1,5 @@ +class Notifications::MarkAllReadsController < ApplicationController + def create + Current.user.notifications.unread.read_all + end +end diff --git a/app/controllers/readings_controller.rb b/app/controllers/readings_controller.rb index 1bf106efd..fb7112b76 100644 --- a/app/controllers/readings_controller.rb +++ b/app/controllers/readings_controller.rb @@ -8,6 +8,6 @@ class ReadingsController < ApplicationController private def mark_bubble_notifications_read - Current.user.notifications.where(bubble: @bubble).update(read_at: Time.current) + Current.user.notifications.where(bubble: @bubble).read_all end end diff --git a/app/models/notification.rb b/app/models/notification.rb index da1cc9614..05d38c940 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -12,6 +12,12 @@ class Notification < ApplicationRecord broadcasts_to ->(notification) { [ notification.user, :notifications ] }, inserts_by: :prepend + class << self + def read_all + update!(read_at: Time.current) + end + end + def read? read_at.present? end diff --git a/app/views/notifications/_tray.html.erb b/app/views/notifications/_tray.html.erb index fa4c650b4..476f0bc78 100644 --- a/app/views/notifications/_tray.html.erb +++ b/app/views/notifications/_tray.html.erb @@ -4,9 +4,9 @@ data: { controller: "dialog", turbo_permanent: true, dialog_modal_value: false, dialog_target: "dialog", action: "keydown.esc->dialog#close:stop click@document->dialog#closeOnClickOutside" } do %> <%= turbo_frame_tag("notifications", src: notifications_tray_path) -%>
- + <% end %> <%= link_to notifications_path, class: "notification-tray__all_action btn flex-item-justify-end" do %> <%= image_tag "bell.svg", aria: { hidden: true }, size: 24 %> diff --git a/app/views/notifications/mark_all_reads/create.html.erb b/app/views/notifications/mark_all_reads/create.html.erb new file mode 100644 index 000000000..52d6bcd10 --- /dev/null +++ b/app/views/notifications/mark_all_reads/create.html.erb @@ -0,0 +1 @@ +<%= turbo_frame_tag "notifications" %> diff --git a/config/routes.rb b/config/routes.rb index 6860a6cf0..bea4b1c2a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -21,6 +21,7 @@ Rails.application.routes.draw do resources :notifications, only: :index namespace :notifications do resource :tray, only: :show + resource :mark_all_read, only: :create end resources :buckets do diff --git a/test/controllers/notifications/mark_all_reads_controller_test.rb b/test/controllers/notifications/mark_all_reads_controller_test.rb new file mode 100644 index 000000000..ea43e1be6 --- /dev/null +++ b/test/controllers/notifications/mark_all_reads_controller_test.rb @@ -0,0 +1,17 @@ +require "test_helper" + +class Notifications::MarkAllReadsControllerTest < ActionDispatch::IntegrationTest + setup do + sign_in_as :kevin + end + + test "show" do + assert_changes -> { notifications(:logo_published_kevin).reload.read? }, from: false, to: true do + assert_changes -> { notifications(:layout_commented_kevin).reload.read? }, from: false, to: true do + post notifications_mark_all_read_url + end + end + + assert_response :success + end +end From 42fa37d347738a6f6cb11fa6d4fc6fc7a6aa9a0a Mon Sep 17 00:00:00 2001 From: Kevin McConnell Date: Tue, 21 Jan 2025 14:47:56 +0000 Subject: [PATCH 13/15] Send beacon request on disconnect as well This is so we can dismiss any notifications that arrived for a bubble while we were viewing that bubble. Otherwise, they'll stick around until we leave the page and come back. --- app/javascript/controllers/beacon_controller.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/javascript/controllers/beacon_controller.js b/app/javascript/controllers/beacon_controller.js index 07182bb36..794565f78 100644 --- a/app/javascript/controllers/beacon_controller.js +++ b/app/javascript/controllers/beacon_controller.js @@ -7,4 +7,8 @@ export default class extends Controller { connect() { post(this.urlValue, { responseKind: "turbo-stream" }) } + + disconnect() { + post(this.urlValue, { responseKind: "turbo-stream" }) + } } From 1f3bc1134f27f4d28b30e4c26ee2a0c3f6c20f16 Mon Sep 17 00:00:00 2001 From: Kevin McConnell Date: Fri, 24 Jan 2025 17:42:36 +0000 Subject: [PATCH 14/15] Paginate the read notifications --- Gemfile | 1 + Gemfile.lock | 4 +++ app/controllers/notifications_controller.rb | 7 ++++-- app/helpers/notifications_helper.rb | 6 +++++ .../fetch_on_visible_controller.js | 25 +++++++++++++++++++ app/views/notifications/index.html.erb | 8 +++--- .../notifications/index.turbo_stream.erb | 7 ++++++ 7 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 app/javascript/controllers/fetch_on_visible_controller.js create mode 100644 app/views/notifications/index.turbo_stream.erb diff --git a/Gemfile b/Gemfile index 5c3b0ff65..fdeb0ea2b 100644 --- a/Gemfile +++ b/Gemfile @@ -22,6 +22,7 @@ gem "thruster", require: false # Features gem "bcrypt", "~> 3.1.7" +gem "geared_pagination", "~> 1.2" gem "rqrcode" gem "redcarpet" gem "rouge" diff --git a/Gemfile.lock b/Gemfile.lock index 26b1c521b..cff4ceb78 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -157,6 +157,9 @@ GEM fugit (1.11.1) et-orbi (~> 1, >= 1.2.11) raabro (~> 1.4) + geared_pagination (1.2.0) + activesupport (>= 5.0) + addressable (>= 2.5.0) globalid (1.2.1) activesupport (>= 6.1) hotwire-spark (0.1.12) @@ -397,6 +400,7 @@ DEPENDENCIES brakeman capybara debug + geared_pagination (~> 1.2) hotwire-spark hotwire_combobox! importmap-rails diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb index 85b656c4c..83e5db488 100644 --- a/app/controllers/notifications_controller.rb +++ b/app/controllers/notifications_controller.rb @@ -1,6 +1,9 @@ class NotificationsController < ApplicationController def index - @read = Current.user.notifications.read.ordered - @unread = Current.user.notifications.unread.ordered + set_page_and_extract_portion_from Current.user.notifications.read.ordered + + if @page.first? + @unread = Current.user.notifications.unread.ordered + end end end diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb index ddc142efb..bb0dade2a 100644 --- a/app/helpers/notifications_helper.rb +++ b/app/helpers/notifications_helper.rb @@ -25,6 +25,12 @@ module NotificationsHelper data: { turbo_frame: "_top" }, & end + def notifications_next_page_link(page) + unless @page.last? + tag.div id: "next_page", data: { controller: "fetch-on-visible", fetch_on_visible_url_value: notifications_path(page: @page.next_param) } + end + end + private def notification_event_action(notification) if notification_is_for_initial_assignement?(notification) diff --git a/app/javascript/controllers/fetch_on_visible_controller.js b/app/javascript/controllers/fetch_on_visible_controller.js new file mode 100644 index 000000000..42f1a36da --- /dev/null +++ b/app/javascript/controllers/fetch_on_visible_controller.js @@ -0,0 +1,25 @@ +import { Controller } from "@hotwired/stimulus" +import { get } from "@rails/request.js" + +export default class extends Controller { + static values = { url: String } + + connect() { + this.#observe() + } + + #observe() { + const observer = new IntersectionObserver((entries) => { + const visible = !!entries.find(entry => entry.isIntersecting) + if (visible) { + this.#fetch() + } + }) + + observer.observe(this.element) + } + + #fetch() { + get(this.urlValue, { responseKind: "turbo-stream" }) + } +} diff --git a/app/views/notifications/index.html.erb b/app/views/notifications/index.html.erb index efbb8c4e9..1f302e623 100644 --- a/app/views/notifications/index.html.erb +++ b/app/views/notifications/index.html.erb @@ -29,9 +29,11 @@ <% end %>
-<% if @read.any? %> -
+<% if @page.records.any? %> +

Previously seen

- <%= render @read %> + <%= render @page.records %>
+ + <%= notifications_next_page_link(@page) %> <% end %> diff --git a/app/views/notifications/index.turbo_stream.erb b/app/views/notifications/index.turbo_stream.erb new file mode 100644 index 000000000..00d744dcd --- /dev/null +++ b/app/views/notifications/index.turbo_stream.erb @@ -0,0 +1,7 @@ +<%= turbo_stream.append :notifications_list_read do %> + <%= render @page.records %> +<% end %> + +<%= turbo_stream.replace :next_page do %> + <%= notifications_next_page_link(@page) %> +<% end %> From 57a1e4d621fb5d080e334a7c66fcd8e82f721fef Mon Sep 17 00:00:00 2001 From: Jason Zimdars Date: Fri, 24 Jan 2025 13:29:48 -0600 Subject: [PATCH 15/15] This shouldn't be here --- app/views/notifications/index.html.erb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/views/notifications/index.html.erb b/app/views/notifications/index.html.erb index 1f302e623..35942d06a 100644 --- a/app/views/notifications/index.html.erb +++ b/app/views/notifications/index.html.erb @@ -11,10 +11,7 @@

<%= @page_title %>

- <%= 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 %> - Add a new project - <% end %> +
<% end %>