From 662ab3f26001f622c136fda6230975751f081438 Mon Sep 17 00:00:00 2001 From: Zach Gollwitzer Date: Wed, 9 Apr 2025 11:16:45 -0400 Subject: [PATCH] Centralize notifications in Notifiable concern --- app/controllers/application_controller.rb | 2 +- app/controllers/concerns/notifiable.rb | 58 +++++++++++++++++++++++ app/helpers/application_helper.rb | 18 ------- 3 files changed, 59 insertions(+), 19 deletions(-) create mode 100644 app/controllers/concerns/notifiable.rb diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 27aba194..61443d46 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,5 +1,5 @@ class ApplicationController < ActionController::Base - include Onboardable, Localize, AutoSync, Authentication, Invitable, SelfHostable, StoreLocation, Impersonatable, Breadcrumbable, FeatureGuardable + include Onboardable, Localize, AutoSync, Authentication, Invitable, SelfHostable, StoreLocation, Impersonatable, Breadcrumbable, FeatureGuardable, Notifiable include Pagy::Backend helper_method :require_upgrade?, :subscription_pending? diff --git a/app/controllers/concerns/notifiable.rb b/app/controllers/concerns/notifiable.rb new file mode 100644 index 00000000..40ce4d0d --- /dev/null +++ b/app/controllers/concerns/notifiable.rb @@ -0,0 +1,58 @@ +module Notifiable + extend ActiveSupport::Concern + + included do + helper_method :render_flash_notifications + helper_method :flash_notification_stream_items + end + + private + def render_flash_notifications + notifications = flash.flat_map { |type, data| resolve_notifications(type, data) } + + view_context.safe_join( + notifications.map { |notification| view_context.render(**notification) } + ) + end + + def flash_notification_stream_items + items = flash.flat_map do |type, data| + notifications = resolve_notifications(type, data) + + if type == "cta" + notifications.map { |notification| turbo_stream.replace("cta", **notification) } + else + notifications.map { |notification| turbo_stream.append("notification-tray", **notification) } + end + end + + # If rendering flash notifications via stream, we mark them as used to avoid + # them being rendered again on the next page load + flash.clear + + items + end + + def resolve_cta(cta) + case cta[:type] + when "category_rule" + { partial: "rules/category_rule_cta", locals: { cta: } } + else + raise "Unknown CTA type: #{cta[:type]}" + end + end + + def resolve_notifications(type, data) + case type + when "alert" + [ { partial: "shared/notifications/alert", locals: { message: data } } ] + when "cta" + [ resolve_cta(data) ] + when "loading" + [ { partial: "shared/notifications/loading", locals: { message: data } } ] + when "notice" + messages = Array(data) + messages.map { |message| { partial: "shared/notifications/notice", locals: { message: message } } } + end + end +end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 1f92cbcd..92ed2411 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -27,24 +27,6 @@ module ApplicationHelper turbo_stream_from Current.family if Current.family end - def render_flash_notifications - notifications = flash.flat_map do |type, data| - case type - when "alert" - render "shared/notifications/alert", message: data - when "cta" - render "shared/notifications/cta", cta: data - when "loading" - render "shared/notifications/loading", message: data - when "notice" - messages = Array(data) - messages.map { |message| render "shared/notifications/notice", message: } - end - end - - safe_join(notifications) - end - ## # Helper to open a centered and overlayed modal with custom contents #