From ceab926d2fbf95f8c3097e1a10ec7f025ac3a2cf Mon Sep 17 00:00:00 2001 From: Pablo Brasero Date: Tue, 14 Apr 2026 10:32:08 +0100 Subject: [PATCH] Form to manage notification preferences --- .rubocop_todo.yml | 2 +- .../notification_preferences_controller.rb | 11 ++++++++ .../user_notification_preferences_helper.rb | 11 ++++++++ app/models/user.rb | 4 +++ app/models/user_notification_preferences.rb | 6 ++++- .../notification_preferences/show.html.erb | 27 +++++++++++++++++++ .../preferences/_navigation.html.erb | 3 +++ config/locales/en.yml | 18 +++++++++++-- config/routes.rb | 1 + test/system/notification_preferences_test.rb | 21 +++++++++++++++ 10 files changed, 100 insertions(+), 4 deletions(-) create mode 100644 app/controllers/preferences/notification_preferences_controller.rb create mode 100644 app/helpers/user_notification_preferences_helper.rb create mode 100644 app/views/preferences/notification_preferences/show.html.erb create mode 100644 test/system/notification_preferences_test.rb diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index cbe6a459e..f7565912e 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -56,7 +56,7 @@ Metrics/BlockNesting: # Offense count: 23 # Configuration parameters: CountComments, CountAsOne. Metrics/ClassLength: - Max: 345 + Max: 342 # Offense count: 72 # Configuration parameters: AllowedMethods, AllowedPatterns. diff --git a/app/controllers/preferences/notification_preferences_controller.rb b/app/controllers/preferences/notification_preferences_controller.rb new file mode 100644 index 000000000..719910b1f --- /dev/null +++ b/app/controllers/preferences/notification_preferences_controller.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module Preferences + class NotificationPreferencesController < PreferencesController + private + + def update_preferences + current_user.notification_preferences.update(params[:user_notification_preferences]) + end + end +end diff --git a/app/helpers/user_notification_preferences_helper.rb b/app/helpers/user_notification_preferences_helper.rb new file mode 100644 index 000000000..74ba53464 --- /dev/null +++ b/app/helpers/user_notification_preferences_helper.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module UserNotificationPreferencesHelper + def user_notification_events + UserNotificationPreferences::EVENTS + end + + def user_notification_mechanisms + UserNotificationPreferences::MECHANISMS + end +end diff --git a/app/models/user.rb b/app/models/user.rb index 07764f124..ceee49b55 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -294,6 +294,10 @@ class User < ApplicationRecord preference.update!(:v => language) end + def notification_preferences + @notification_preferences ||= UserNotificationPreferences.new(self) + end + def home_location? home_lat && home_lon end diff --git a/app/models/user_notification_preferences.rb b/app/models/user_notification_preferences.rb index 348d7fa60..5653c2418 100644 --- a/app/models/user_notification_preferences.rb +++ b/app/models/user_notification_preferences.rb @@ -1,6 +1,9 @@ # frozen_string_literal: true class UserNotificationPreferences + extend ActiveModel::Naming + include ActiveModel::Conversion + EVENTS = %w[ changeset_comment diary_comment @@ -39,7 +42,8 @@ class UserNotificationPreferences end end - # One getter method for each event. + # One getter method for each event. Required by ActionView + # to render the form, but also generally useful to us. EVENTS.each do |event_name| define_method event_name do prefs = diff --git a/app/views/preferences/notification_preferences/show.html.erb b/app/views/preferences/notification_preferences/show.html.erb new file mode 100644 index 000000000..0ab2c016b --- /dev/null +++ b/app/views/preferences/notification_preferences/show.html.erb @@ -0,0 +1,27 @@ +<% content_for :heading_class, "pb-0" %> + +<% content_for :heading do %> +

<%= t ".title" %>

+ <%= render :partial => "navigation" %> +<% end %> + +<%= bootstrap_form_for current_user.notification_preferences, :method => :patch, :url => { :action => :update } do |f| %> +
+ <% user_notification_events.each do |event_name| %> +
+ <%= f.collection_check_boxes( + event_name, + user_notification_mechanisms, + :itself, + ->(mechanism) { t(".delivery_mechanisms.#{mechanism}") }, + :label => { + :text => t(".#{event_name}"), + :class => "fw-bold fs-6" + } + ) %> +
+ <% end %> +
+ + <%= f.primary t(".save") %> +<% end %> diff --git a/app/views/preferences/preferences/_navigation.html.erb b/app/views/preferences/preferences/_navigation.html.erb index 00b7cf7bc..cd6f70e38 100644 --- a/app/views/preferences/preferences/_navigation.html.erb +++ b/app/views/preferences/preferences/_navigation.html.erb @@ -4,6 +4,9 @@ + diff --git a/config/locales/en.yml b/config/locales/en.yml index fea147731..050e9c9b2 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2113,8 +2113,9 @@ en: update_success_flash: message: Preferences updated. navigation: - preferences: Preferences - advanced_preferences: Advanced Preferences + preferences: Interface + notification_preferences: Notifications + advanced_preferences: Advanced basic_preferences: show: title: My Preferences @@ -2135,6 +2136,19 @@ en: light: Light dark: Dark save: Update Preferences + notification_preferences: + show: + title: Notification Preferences + changeset_comment: Changeset comments + diary_comment: Diary comments + direct_message: Direct messages + gpx_import_failure: "GPS trace import: failure" + gpx_import_success: "GPX trace import: success" + new_follower: New followers + note_comment: Note comments + save: Update Preferences + delivery_mechanisms: + email: Email advanced_preferences: show: title: My Advanced Preferences diff --git a/config/routes.rb b/config/routes.rb index c0cf75d7e..e63bed58e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -339,6 +339,7 @@ OpenStreetMap::Application.routes.draw do scope :preferences, :module => :preferences do resource :basic_preferences, :path => "basic", :only => [:show, :update] + resource :notification_preferences, :path => "notifications", :only => [:show, :update] resource :advanced_preferences, :path => "advanced", :only => [:show, :update] end get "/preferences", :to => redirect(:path => "/preferences/basic"), :as => nil diff --git a/test/system/notification_preferences_test.rb b/test/system/notification_preferences_test.rb new file mode 100644 index 000000000..4bffdb47b --- /dev/null +++ b/test/system/notification_preferences_test.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +require "application_system_test_case" + +class NotificationPreferencesTest < ApplicationSystemTestCase + test "toggling preferences" do + user = create(:user) + sign_in_as(user) + + visit notification_preferences_path + + assert_selector ".notification_preferences input:checked", :count => 7 + + uncheck "user_notification_preferences_new_follower_email" + uncheck "user_notification_preferences_gpx_import_success_email" + click_on "Update Preferences" + + assert_selector ".notification_preferences input:checked", :count => 5 + assert_selector "input#user_notification_preferences_new_follower_email:not(checked)" + end +end -- 2.39.5