Skip to content

Commit

Permalink
Feature: User edit profile page will allow you to manually select you…
Browse files Browse the repository at this point in the history
…r time zone
  • Loading branch information
robguthrie committed Feb 28, 2024
1 parent fad8ba5 commit c514727
Show file tree
Hide file tree
Showing 13 changed files with 56 additions and 15 deletions.
1 change: 1 addition & 0 deletions Gemfile
Expand Up @@ -64,6 +64,7 @@ gem 'blazer'
gem 'terminal-table'
gem 'tzinfo-data'
gem 'pg_search'
gem 'i18n-timezones'

group :development, :test do
gem 'listen'
Expand Down
4 changes: 4 additions & 0 deletions Gemfile.lock
Expand Up @@ -305,6 +305,9 @@ GEM
httpclient (2.8.3)
i18n (1.14.1)
concurrent-ruby (~> 1.0)
i18n-timezones (1.4.8)
i18n (>= 0.9.3)
rails (>= 5.1.6.2)
icalendar (2.10.1)
ice_cube (~> 0.16)
ice_cube (0.16.4)
Expand Down Expand Up @@ -633,6 +636,7 @@ DEPENDENCIES
hiredis
http_accept_language
httparty (~> 0.21.0)
i18n-timezones
icalendar
image_processing (~> 1.12)
listen
Expand Down
10 changes: 10 additions & 0 deletions app/controllers/api/v1/profile_controller.rb
Expand Up @@ -28,6 +28,16 @@ def time_zones
render json: time_zones, root: false
end

def all_time_zones
zones = ActiveSupport::TimeZone.all.map do |tz|
{
title: I18n.t("timezones.#{tz.name}", default: tz.name, locale: params[:selected_locale]),
value: tz.tzinfo.name
}
end
render json: zones, root: false
end

def mentionable_users
instantiate_collection do |collection|
collection.distinct.mention_search(current_user, model, String(params[:q]).strip.delete("\u0000"))
Expand Down
4 changes: 3 additions & 1 deletion app/models/logged_out_user.rb
@@ -1,7 +1,7 @@
class LoggedOutUser
include Null::User
include AvatarInitials
attr_accessor :name, :email, :token, :avatar_initials, :locale, :legal_accepted, :recaptcha, :time_zone, :date_time_pref
attr_accessor :name, :email, :token, :avatar_initials, :locale, :legal_accepted, :recaptcha, :time_zone, :date_time_pref, :autodetect_time_zone

alias :read_attribute_for_serialization :send

Expand All @@ -16,12 +16,14 @@ def initialize(name: nil, email: nil, token: nil, locale: I18n.locale, time_zone
@locale = locale
@date_time_pref = date_time_pref
@time_zone = time_zone
@autodetect_time_zone = true
@params = params
@session = session
apply_null_methods!
set_avatar_initials if (@name || @email)
end


def name_or_username
@name || @username
end
Expand Down
2 changes: 1 addition & 1 deletion app/models/permitted_params.rb
Expand Up @@ -19,7 +19,7 @@ class PermittedParams < Struct.new(:params)
def user_attributes
[:name, :avatar_kind, :email, :password, :password_confirmation, :current_password,
:remember_me, :uploaded_avatar, :username, :short_bio, :short_bio_format, :location,
:time_zone, :selected_locale, :email_when_mentioned, :default_membership_volume,
:autodetect_time_zone, :time_zone, :selected_locale, :email_when_mentioned, :default_membership_volume,
:email_catch_up_day, :has_password, :has_token, :email_status,
:email_when_proposal_closing_soon, :email_new_discussions_and_proposals, :email_on_participation, :email_newsletter,
:date_time_pref, :bot,
Expand Down
1 change: 1 addition & 0 deletions app/serializers/user_serializer.rb
Expand Up @@ -4,6 +4,7 @@ class UserSerializer < AuthorSerializer
:content_locale,
:location,
:has_password,
:autodetect_time_zone,
:avatar_url,
:attachments,
:date_time_pref
Expand Down
1 change: 1 addition & 0 deletions config/locales/client.en.yml
Expand Up @@ -1461,6 +1461,7 @@ en:
email_sent: "Email sent to %{name}"

profile_page:
autodetect_time_zone: Autodetect time zone
account_is_bot: This is a bot account
bot_account_warning: Bot accounts will not be invited to vote in polls or participate in discussions
incomplete_profile: Incomplete profile!
Expand Down
1 change: 1 addition & 0 deletions config/routes.rb
Expand Up @@ -136,6 +136,7 @@ def dev_routes_for(namespace)
resources :profile, only: [:show, :index] do
collection do
get :time_zones
get :all_time_zones
get :mentionable_users
get :me
get :groups
Expand Down
@@ -0,0 +1,5 @@
class AddAutodetectTimeZoneBooleanToUsers < ActiveRecord::Migration[7.0]
def change
add_column :users, :autodetect_time_zone, :boolean, default: true, null: false
end
end
3 changes: 2 additions & 1 deletion db/schema.rb
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.0].define(version: 2024_02_04_194803) do
ActiveRecord::Schema[7.0].define(version: 2024_02_27_225748) do
# These are extensions that must be enabled in order to support this database
enable_extension "citext"
enable_extension "hstore"
Expand Down Expand Up @@ -1027,6 +1027,7 @@
t.string "date_time_pref"
t.string "api_key"
t.integer "deactivator_id"
t.boolean "autodetect_time_zone", default: true, null: false
t.index ["api_key"], name: "index_users_on_api_key"
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["email_verified"], name: "index_users_on_email_verified"
Expand Down
36 changes: 25 additions & 11 deletions vue/src/components/profile/page.vue
Expand Up @@ -17,7 +17,8 @@ export default {
user: null,
originalUser: null,
existingEmails: [],
currentTime: new Date()
currentTime: new Date(),
timeZones: []
};
},
Expand All @@ -26,7 +27,7 @@ export default {
this.init();
EventBus.$emit('currentComponent', { titleKey: 'profile_page.edit_profile', page: 'profilePage'});
EventBus.$on('updateProfile', this.init);
return EventBus.$on('signedIn', this.init);
EventBus.$on('signedIn', this.init);
},
beforeDestroy() {
Expand All @@ -47,14 +48,32 @@ export default {
emailExists() { return includes(this.existingEmails, this.user.email); }
},
watch: {
'user.autodetectTimeZone'(val) {
if (val) {this.user.timeZone = AppConfig.timeZone }
},
'user.selectedLocale'(val) {
this.fetchTimeZones();
}
},
methods: {
init() {
if (!Session.isSignedIn()) { return; }
this.originalUser = Session.user();
this.user = this.originalUser.clone();
this.fetchTimeZones();
Session.updateLocale(this.user.locale);
},
fetchTimeZones() {
const locale = this.user.selectedLocale || this.user.locale
Records.fetch({path: 'profile/all_time_zones', params: {selected_locale: locale}}).then(data => {
this.timeZones = data
})
},
changePicture() {
openModal({component: 'ChangePictureForm'});
},
Expand Down Expand Up @@ -164,15 +183,10 @@ v-main
item-text="name"
item-value="key")
validation-errors(:subject='user', field='selectedLocale')
p
span(v-t="'common.time_zone'")
space
span {{user.timeZone}}
space
v-tooltip(top)
template(v-slot:activator="{on, attrs}")
common-icon(v-bind="attrs" v-on="on" small name="mdi-information-outline")
span(v-t="'profile_page.updated_on_sign_in'")

v-checkbox(v-model="user.autodetectTimeZone" :label="$t('profile_page.autodetect_time_zone')")
v-select(v-model="user.timeZone" :items="timeZones" :label="$t('common.time_zone')" item-text="title" item-value="value" :disabled="user.autodetectTimeZone")

v-checkbox(v-model="user.bot" :label="$t('profile_page.account_is_bot')")
v-alert(v-if="user.bot" type="warning")
span(v-t="'profile_page.bot_account_warning'")
Expand Down
1 change: 1 addition & 0 deletions vue/src/shared/models/user_model.js
Expand Up @@ -14,6 +14,7 @@ export default class UserModel extends BaseModel {

defaultValues() {
return {
autodetectTimeZone: false,
shortBio: '',
shortBioFormat: 'html',
files: [],
Expand Down
2 changes: 1 addition & 1 deletion vue/src/shared/services/session.js
Expand Up @@ -83,7 +83,7 @@ export default new class Session {
this.updateLocale(user.locale);

if (this.isSignedIn()) {
if (user.timeZone !== AppConfig.timeZone) {
if (user.autodetectTimeZone && user.timeZone !== AppConfig.timeZone) {
user.timeZone = AppConfig.timeZone;
Records.users.updateProfile(user);
}
Expand Down

0 comments on commit c514727

Please sign in to comment.