diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index e0e50c25b..678f4b7aa 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -87,6 +87,6 @@ class ApplicationController < ActionController::Base end def set_time_zone(&block) - Time.use_zone(current_user.time_zone, &block) + Time.use_zone(current_user.settings[:time_zone], &block) end end diff --git a/app/controllers/users/invitations_controller.rb b/app/controllers/users/invitations_controller.rb index bd199cd7a..2e34622bc 100644 --- a/app/controllers/users/invitations_controller.rb +++ b/app/controllers/users/invitations_controller.rb @@ -180,7 +180,7 @@ module Users message: sanitize_input(message) ) - if target_user.assignments_notification + if target_user.settings[:notifications][:assignments] UserNotification.create(notification: notification, user: target_user) end end diff --git a/app/controllers/users/settings/account/preferences_controller.rb b/app/controllers/users/settings/account/preferences_controller.rb index ac85f0148..4cfc94463 100644 --- a/app/controllers/users/settings/account/preferences_controller.rb +++ b/app/controllers/users/settings/account/preferences_controller.rb @@ -77,15 +77,15 @@ module Users end def notifications_settings - @user.assignments_notification = + @user.settings[:notifications][:assignments] = params[:assignments_notification] ? true : false - @user.recent_notification = + @user.settings[:notifications][:recent] = params[:recent_notification] ? true : false - @user.recent_notification_email = + @user.settings[:notifications][:recent_email] = params[:recent_notification_email] ? true : false - @user.assignments_notification_email = + @user.settings[:notifications][:assignments_email] = params[:assignments_notification_email] ? true : false - @user.system_message_notification_email = + @user.settings[:notifications][:system_message_email] = params[:system_message_notification_email] ? true : false if @user.save diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 501fa65ac..1713b706c 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -100,7 +100,7 @@ module ApplicationHelper title: sanitize_input(title), message: sanitize_input(message) ) - if target_user.assignments_notification + if target_user.settings[:notifications][:assignments] UserNotification.create(notification: notification, user: target_user) end end diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb index f41eb90ac..248fd5b11 100644 --- a/app/helpers/notifications_helper.rb +++ b/app/helpers/notifications_helper.rb @@ -44,7 +44,7 @@ module NotificationsHelper message: sanitize_input(message) ) - if target_user.assignments_notification + if target_user.settings[:notifications][:assignments] UserNotification.create(notification: notification, user: target_user) end end diff --git a/app/models/activity.rb b/app/models/activity.rb index e4dd2d029..ea4eaa90a 100644 --- a/app/models/activity.rb +++ b/app/models/activity.rb @@ -118,9 +118,9 @@ class Activity < ApplicationRecord project.users.each do |project_user| next if project_user == user - next if !project_user.assignments_notification && + next if !project_user.settings[:notifications][:assignments] && notification.type_of == 'assignment' - next if !project_user.recent_notification && + next if !project_user.settings[:notifications][:recent] && notification.type_of == 'recent_changes' UserNotification.create(notification: notification, user: project_user) end diff --git a/app/models/concerns/settings_model.rb b/app/models/concerns/settings_model.rb new file mode 100644 index 000000000..c74425422 --- /dev/null +++ b/app/models/concerns/settings_model.rb @@ -0,0 +1,22 @@ +module SettingsModel + extend ActiveSupport::Concern + + @@default_settings = HashWithIndifferentAccess.new + + included do + serialize :settings, JsonbHashSerializer + after_initialize :init_default_settings, if: :new_record? + end + + class_methods do + def default_settings(dfs) + @@default_settings.merge!(dfs) + end + end + + protected + + def init_default_settings + self.settings = @@default_settings + end +end diff --git a/app/models/user.rb b/app/models/user.rb index c7c5fb3dd..ec10c4b30 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,5 +1,6 @@ class User < ApplicationRecord include SearchableModel + include SettingsModel acts_as_token_authenticatable devise :invitable, :confirmable, :database_authenticatable, :registerable, @@ -33,9 +34,21 @@ class User < ApplicationRecord validates_attachment :avatar, :content_type => { :content_type => ["image/jpeg", "image/png"] }, size: { less_than: Constants::AVATAR_MAX_SIZE_MB.megabytes } - validates :time_zone, presence: true validate :time_zone_check + store_accessor :settings, :time_zone + + default_settings( + time_zone: 'UTC', + notifications: { + assignments: true, + assignments_email: false, + recent: true, + recent_email: false, + system_message_email: false + } + ) + # Relations has_many :user_teams, inverse_of: :user has_many :teams, through: :user_teams @@ -384,7 +397,8 @@ class User < ApplicationRecord end def time_zone_check - if time_zone.nil? or ActiveSupport::TimeZone.new(time_zone).nil? + if time_zone.nil? || + ActiveSupport::TimeZone.new(time_zone).nil? errors.add(:time_zone) end end diff --git a/app/models/user_notification.rb b/app/models/user_notification.rb index 98593e5d7..ba9e494e3 100644 --- a/app/models/user_notification.rb +++ b/app/models/user_notification.rb @@ -40,17 +40,17 @@ class UserNotification < ApplicationRecord send_email_notification( user, notification - ) if user.system_message_notification_email + ) if user.settings[:notifications][:system_message_email] when 'assignment' send_email_notification( user, notification - ) if user.assignments_notification_email + ) if user.settings[:notifications][:assignments_email] when 'recent_changes' send_email_notification( user, notification - ) if user.recent_notification_email + ) if user.settings[:notifications][:recent_email] when 'deliver' send_email_notification( user, diff --git a/app/serializers/jsonb_hash_serializer.rb b/app/serializers/jsonb_hash_serializer.rb new file mode 100644 index 000000000..f01f29560 --- /dev/null +++ b/app/serializers/jsonb_hash_serializer.rb @@ -0,0 +1,11 @@ +class JsonbHashSerializer + def self.dump(hash) + hash.to_json + end + + def self.load(hash) + hash ||= {} + hash = JSON.parse(hash) if hash.instance_of? String + hash.with_indifferent_access + end +end diff --git a/app/views/users/settings/account/preferences/index.html.erb b/app/views/users/settings/account/preferences/index.html.erb index 18ed8eeae..e982e6522 100644 --- a/app/views/users/settings/account/preferences/index.html.erb +++ b/app/views/users/settings/account/preferences/index.html.erb @@ -12,7 +12,11 @@ <%= form_for(@user, url: update_preferences_path(format: :json), remote: true, - html: { method: :put, 'data-for' => 'time_zone' }) do |f| %> + html: { + method: :put, + 'data-for' => 'settings[time_zone]', + 'data-turbolinks' => false + }) do |f| %>
<%= f.label t("users.settings.account.preferences.edit.time_zone_label") %> @@ -21,9 +25,9 @@ disabled="disabled" autocomplete="off" type="text" - value="<%= @user.time_zone %>" - name="fake_user[time_zone]" - id="fake_user_time_zone"> + value="<%= @user.settings[:time_zone] %>" + name="fake_user[settings][time_zone]" + id="fake_user_settings_time_zone"> <%=t "general.edit" %> @@ -35,7 +39,7 @@

<%=t "users.settings.account.preferences.edit.time_zone_title" %>

- <%= f.select :time_zone, ActiveSupport::TimeZone.all.collect { |tz| + <%= f.select :time_zone , ActiveSupport::TimeZone.all.collect { |tz| [tz.formatted_offset + " " + tz.name, tz.name] }, {}, {class: 'form-control selectpicker', 'ata-role' => 'clear'} %> <%= t("users.settings.account.preferences.edit.time_zone_sublabel") %> @@ -75,7 +79,7 @@ <%=t 'notifications.form.notification_scinote' %>
- <%= check_box_tag :assignments_notification, @user.assignments_notification %> + <%= check_box_tag :assignments_notification, @user.settings[:notifications][:assignments] %>
@@ -83,7 +87,7 @@ <%=t 'notifications.form.notification_email' %>
- <%= check_box_tag :assignments_notification_email, @user.assignments_notification_email %> + <%= check_box_tag :assignments_notification_email, @user.settings[:notifications][:assignments_email] %>
@@ -100,7 +104,7 @@ <%=t 'notifications.form.notification_scinote' %>
- <%= check_box_tag :recent_notification, @user.recent_notification %> + <%= check_box_tag :recent_notification, @user.settings[:notifications][:recent] %>
@@ -108,7 +112,7 @@ <%=t 'notifications.form.notification_email' %>
- <%= check_box_tag :recent_notification_email, @user.recent_notification_email %> + <%= check_box_tag :recent_notification_email, @user.settings[:notifications][:recent_email] %>
@@ -133,7 +137,7 @@ <%=t 'notifications.form.notification_email' %>
- <%= check_box_tag :system_message_notification_email, @user.system_message_notification_email %> + <%= check_box_tag :system_message_notification_email, @user.settings[:notifications][:system_message_email] %>
diff --git a/db/migrate/20170809131000_refactor_user_settings.rb b/db/migrate/20170809131000_refactor_user_settings.rb new file mode 100644 index 000000000..4dd54cf8d --- /dev/null +++ b/db/migrate/20170809131000_refactor_user_settings.rb @@ -0,0 +1,53 @@ +class RefactorUserSettings < ActiveRecord::Migration[5.1] + def up + add_column :users, :settings, :jsonb, default: {}, null: false + + User.find_each do |user| + settings = { + time_zone: user['time_zone'], + notifications: { + assignments: user['assignments_notification'], + assignments_email: user['assignments_notification_email'], + recent: user['recent_notification'], + recent_email: user['recent_notification_email'], + system_message_email: user['system_message_notification_email'] + } + } + user.update(settings: settings) + end + + remove_column :users, :time_zone, :string + remove_column :users, :assignments_notification, :boolean + remove_column :users, :assignments_notification_email, :boolean + remove_column :users, :recent_notification, :boolean + remove_column :users, :recent_notification_email, :boolean + remove_column :users, :system_message_notification_email, :boolean + end + + def down + add_column :users, :time_zone, :string, default: false + add_column :users, :assignments_notification, :boolean, default: false + add_column :users, :assignments_notification_email, :boolean, default: false + add_column :users, :recent_notification, :boolean, default: false + add_column :users, :recent_notification_email, :boolean, default: false + add_column :users, + :system_message_notification_email, :boolean, default: false + + User.find_each do |user| + user.time_zone = user.settings[:time_zone] + user.assignments_notification = + user.settings[:notifications][:assignments] + user.assignments_notification_email = + user.settings[:notifications][:assignments_email] + user.recent_notification = + user.settings[:notifications][:recent] + user.recent_notification_email = + user.settings[:notifications][:recent_email] + user.system_message_notification_email = + user.settings[:notifications][:system_message_email] + user.save + end + + remove_column :users, :settings, :jsonb + end +end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index aa55b0a06..b4c1515d7 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -28,7 +28,6 @@ describe User, type: :model do it { should have_db_column :confirmed_at } it { should have_db_column :confirmation_sent_at } it { should have_db_column :unconfirmed_email } - it { should have_db_column :time_zone } it { should have_db_column :invitation_token } it { should have_db_column :invitation_created_at } it { should have_db_column :invitation_sent_at } @@ -38,12 +37,8 @@ describe User, type: :model do it { should have_db_column :invited_by_type } it { should have_db_column :invitations_count } it { should have_db_column :tutorial_status } - it { should have_db_column :assignments_notification } - it { should have_db_column :recent_notification } - it { should have_db_column :assignments_notification_email } - it { should have_db_column :recent_notification_email } + it { should have_db_column :settings } it { should have_db_column :current_team_id } - it { should have_db_column :system_message_notification_email } it { should have_db_column :authentication_token } end @@ -115,7 +110,7 @@ describe User, type: :model do it { should validate_presence_of :full_name } it { should validate_presence_of :initials } it { should validate_presence_of :email } - it { should validate_presence_of :time_zone } + it { should validate_presence_of :settings } it do should validate_length_of(:full_name).is_at_most(