diff --git a/app/controllers/concerns/current_timezone.rb b/app/controllers/concerns/current_timezone.rb index 9c36757c8..9c63ba679 100644 --- a/app/controllers/concerns/current_timezone.rb +++ b/app/controllers/concerns/current_timezone.rb @@ -3,6 +3,8 @@ module CurrentTimezone included do around_action :set_current_timezone + + helper_method :timezone_from_cookie end private @@ -12,6 +14,6 @@ module CurrentTimezone def timezone_from_cookie timezone = cookies[:timezone] - timezone if timezone.present? && ActiveSupport::TimeZone[timezone] + ActiveSupport::TimeZone[timezone] if timezone.present? end end diff --git a/app/controllers/my/timezones_controller.rb b/app/controllers/my/timezones_controller.rb new file mode 100644 index 000000000..c70d7e80a --- /dev/null +++ b/app/controllers/my/timezones_controller.rb @@ -0,0 +1,10 @@ +class My::TimezonesController < ApplicationController + def update + Current.user.settings.update!(timezone_name: timezone_param) + end + + private + def timezone_param + params[:timezone_name] + end +end diff --git a/app/models/user/configurable.rb b/app/models/user/configurable.rb index cec3b6670..c80268866 100644 --- a/app/models/user/configurable.rb +++ b/app/models/user/configurable.rb @@ -6,5 +6,7 @@ module User::Configurable has_many :push_subscriptions, class_name: "Push::Subscription", dependent: :delete_all after_create :create_settings, unless: :system? + + delegate :timezone, to: :settings, allow_nil: true end end diff --git a/app/models/user/settings.rb b/app/models/user/settings.rb index 9db9edd24..c99d8c135 100644 --- a/app/models/user/settings.rb +++ b/app/models/user/settings.rb @@ -23,6 +23,10 @@ class User::Settings < ApplicationRecord !bundle_email_never? end + def timezone + ActiveSupport::TimeZone[timezone_name] if timezone_name.present? + end + private def review_pending_bundles if bundling_emails? diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 9f62fc73b..d716fb07d 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -9,6 +9,7 @@ <%= render "layouts/shared/flash" %> + <%= render "layouts/shared/time_zone" %>
<%= yield %> diff --git a/app/views/layouts/shared/_time_zone.html.erb b/app/views/layouts/shared/_time_zone.html.erb new file mode 100644 index 000000000..5eb6e1f6d --- /dev/null +++ b/app/views/layouts/shared/_time_zone.html.erb @@ -0,0 +1,5 @@ +<% if timezone_from_cookie.present? && timezone_from_cookie != Current.user.timezone %> + <%= auto_submit_form_with url: my_timezone_path, method: :put do %> + <%= hidden_field_tag :timezone_name, timezone_from_cookie.name %> + <% end %> +<% end %> diff --git a/config/routes.rb b/config/routes.rb index 348e3254f..554545c2f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -119,6 +119,7 @@ Rails.application.routes.draw do namespace :my do resources :pins + resource :timezone end namespace :prompts do diff --git a/db/migrate/20250905093718_add_timezone_name_to_user_settings.rb b/db/migrate/20250905093718_add_timezone_name_to_user_settings.rb new file mode 100644 index 000000000..c53da0916 --- /dev/null +++ b/db/migrate/20250905093718_add_timezone_name_to_user_settings.rb @@ -0,0 +1,5 @@ +class AddTimezoneNameToUserSettings < ActiveRecord::Migration[8.1] + def change + add_column :user_settings, :timezone_name, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index 2abd352ca..b7ac2e5ce 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_09_02_093943) do +ActiveRecord::Schema[8.1].define(version: 2025_09_05_093718) do create_table "accesses", force: :cascade do |t| t.datetime "accessed_at" t.integer "collection_id", null: false @@ -426,6 +426,7 @@ ActiveRecord::Schema[8.1].define(version: 2025_09_02_093943) do create_table "user_settings", force: :cascade do |t| t.integer "bundle_email_frequency", default: 0, null: false t.datetime "created_at", null: false + t.string "timezone_name" t.datetime "updated_at", null: false t.integer "user_id", null: false t.index ["user_id", "bundle_email_frequency"], name: "index_user_settings_on_user_id_and_bundle_email_frequency" diff --git a/db/schema_cache.yml b/db/schema_cache.yml index 8dde46954..7c3895d32 100644 --- a/db/schema_cache.yml +++ b/db/schema_cache.yml @@ -1246,6 +1246,16 @@ columns: comment: - *5 - *6 + - !ruby/object:ActiveRecord::ConnectionAdapters::SQLite3::Column + auto_increment: + name: timezone_name + cast_type: *7 + sql_type_metadata: *8 + 'null': true + default: + default_function: + collation: + comment: - *9 - *18 users: @@ -2996,4 +3006,4 @@ indexes: comment: valid: true workflows: [] -version: 20250902093943 +version: 20250905093718 diff --git a/test/controllers/my/timezones_controller_test.rb b/test/controllers/my/timezones_controller_test.rb new file mode 100644 index 000000000..98d45e304 --- /dev/null +++ b/test/controllers/my/timezones_controller_test.rb @@ -0,0 +1,15 @@ +require "test_helper" + +class My::TimezonesControllerTest < ActionDispatch::IntegrationTest + setup do + sign_in_as :kevin + end + + test "update" do + time_zone = ActiveSupport::TimeZone["America/New_York"] + + assert_not_equal time_zone, users(:kevin).timezone + patch my_timezone_path, params: { timezone_name: "America/New_York" } + assert_equal time_zone, users(:kevin).reload.timezone + end +end