Add timezone field in UserProfile.

Implements backend of #1506.
This commit is contained in:
Umair Khan 2017-03-14 14:53:09 +05:00 committed by Tim Abbott
parent 0d296afa54
commit 242d3ffaf4
8 changed files with 83 additions and 3 deletions

View File

@ -2359,6 +2359,18 @@ def do_change_default_language(user_profile, setting_value, log=True):
log_event(event) log_event(event)
send_event(event, [user_profile.id]) send_event(event, [user_profile.id])
def do_change_timezone(user_profile, setting_value, log=True):
# type: (UserProfile, Text, bool) -> None
user_profile.timezone = setting_value
user_profile.save(update_fields=['timezone'])
event = {'type': 'update_display_settings',
'user': user_profile.email,
'setting_name': 'timezone',
'setting': setting_value}
if log:
log_event(event)
send_event(event, [user_profile.id])
def set_default_streams(realm, stream_dict): def set_default_streams(realm, stream_dict):
# type: (Realm, Dict[Text, Dict[Text, Any]]) -> None # type: (Realm, Dict[Text, Dict[Text, Any]]) -> None
DefaultStream.objects.filter(realm=realm).delete() DefaultStream.objects.filter(realm=realm).delete()

9
zerver/lib/timezone.py Normal file
View File

@ -0,0 +1,9 @@
from __future__ import absolute_import
from typing import Text, List
import pytz
def get_all_timezones():
# type: () -> List[Text]
return sorted(pytz.all_timezones)

View File

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.5 on 2017-03-15 11:43
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('zerver', '0060_move_avatars_to_be_uid_based'),
]
operations = [
migrations.AddField(
model_name='userprofile',
name='timezone',
field=models.CharField(default='UTC', max_length=40),
),
]

View File

@ -609,6 +609,9 @@ class UserProfile(ModelReprMixin, AbstractBaseUser, PermissionsMixin):
DEFAULT_UPLOADS_QUOTA = 1024*1024*1024 DEFAULT_UPLOADS_QUOTA = 1024*1024*1024
quota = models.IntegerField(default=DEFAULT_UPLOADS_QUOTA) # type: int quota = models.IntegerField(default=DEFAULT_UPLOADS_QUOTA) # type: int
# The maximum length of a timezone in pytz.all_timezones is 32.
# Setting max_length=40 is a safe choice.
timezone = models.CharField(max_length=40, default='UTC') # type: Text
def can_admin_user(self, target_user): def can_admin_user(self, target_user):
# type: (UserProfile) -> bool # type: (UserProfile) -> bool

View File

@ -124,6 +124,7 @@ class HomeTest(ZulipTestCase):
"stream_sounds_enabled", "stream_sounds_enabled",
"subbed_info", "subbed_info",
"test_suite", "test_suite",
"timezone",
"twenty_four_hour_time", "twenty_four_hour_time",
"unread_count", "unread_count",
"unsubbed_info", "unsubbed_info",

View File

@ -216,6 +216,29 @@ class ChangeSettingsTest(ZulipTestCase):
user_profile = get_user_profile_by_email(email) user_profile = get_user_profile_by_email(email)
self.assertNotEqual(user_profile.default_language, invalid_lang) self.assertNotEqual(user_profile.default_language, invalid_lang)
def test_change_timezone(self):
# type: () -> None
"""
Test changing the timezone of the user.
"""
email = "hamlet@zulip.com"
self.login(email)
usa_pacific = 'US/Pacific'
data = dict(timezone=ujson.dumps(usa_pacific))
result = self.client_patch("/json/settings/display", data)
self.assert_json_success(result)
user_profile = get_user_profile_by_email(email)
self.assertEqual(user_profile.timezone, usa_pacific)
# Test to make sure invalid timezones are not accepted
# and saved in the db.
invalid_timezone = "invalid_timezone"
data = dict(timezone=ujson.dumps(invalid_timezone))
result = self.client_patch("/json/settings/display", data)
self.assert_json_error(result, "Invalid timezone '%s'" % (invalid_timezone,))
user_profile = get_user_profile_by_email(email)
self.assertNotEqual(user_profile.timezone, invalid_timezone)
class UserChangesTest(ZulipTestCase): class UserChangesTest(ZulipTestCase):
def test_update_api_key(self): def test_update_api_key(self):
# type: () -> None # type: () -> None

View File

@ -233,6 +233,7 @@ def home_real(request):
avatar_url = avatar_url(user_profile), avatar_url = avatar_url(user_profile),
avatar_url_medium = avatar_url(user_profile, medium=True), avatar_url_medium = avatar_url(user_profile, medium=True),
avatar_source = user_profile.avatar_source, avatar_source = user_profile.avatar_source,
timezone = user_profile.timezone,
# Stream message notification settings: # Stream message notification settings:
stream_desktop_notifications_enabled = user_profile.enable_stream_desktop_notifications, stream_desktop_notifications_enabled = user_profile.enable_stream_desktop_notifications,

View File

@ -23,7 +23,7 @@ from zerver.lib.actions import do_change_password, \
do_regenerate_api_key, do_change_avatar_fields, do_change_twenty_four_hour_time, \ do_regenerate_api_key, do_change_avatar_fields, do_change_twenty_four_hour_time, \
do_change_left_side_userlist, do_change_emoji_alt_code, do_change_default_language, \ do_change_left_side_userlist, do_change_emoji_alt_code, do_change_default_language, \
do_change_pm_content_in_desktop_notifications, validate_email, \ do_change_pm_content_in_desktop_notifications, validate_email, \
do_change_user_email, do_start_email_change_process do_change_user_email, do_start_email_change_process, do_change_timezone
from zerver.lib.avatar import avatar_url from zerver.lib.avatar import avatar_url
from zerver.lib.i18n import get_available_language_codes from zerver.lib.i18n import get_available_language_codes
from zerver.lib.response import json_success, json_error from zerver.lib.response import json_success, json_error
@ -31,6 +31,7 @@ from zerver.lib.upload import upload_avatar_image
from zerver.lib.validator import check_bool, check_string from zerver.lib.validator import check_bool, check_string
from zerver.lib.request import JsonableError from zerver.lib.request import JsonableError
from zerver.lib.users import check_change_full_name from zerver.lib.users import check_change_full_name
from zerver.lib.timezone import get_all_timezones
from zerver.models import UserProfile, Realm, name_changes_disabled, \ from zerver.models import UserProfile, Realm, name_changes_disabled, \
EmailChangeStatus EmailChangeStatus
from confirmation.models import EmailChangeConfirmation from confirmation.models import EmailChangeConfirmation
@ -158,12 +159,17 @@ def update_display_settings_backend(request, user_profile,
twenty_four_hour_time=REQ(validator=check_bool, default=None), twenty_four_hour_time=REQ(validator=check_bool, default=None),
default_language=REQ(validator=check_string, default=None), default_language=REQ(validator=check_string, default=None),
left_side_userlist=REQ(validator=check_bool, default=None), left_side_userlist=REQ(validator=check_bool, default=None),
emoji_alt_code=REQ(validator=check_bool, default=None)): emoji_alt_code=REQ(validator=check_bool, default=None),
# type: (HttpRequest, UserProfile, Optional[bool], Optional[str], Optional[bool], Optional[bool]) -> HttpResponse timezone=REQ(validator=check_string, default=None)):
# type: (HttpRequest, UserProfile, Optional[bool], Optional[str], Optional[bool], Optional[bool], Optional[Text]) -> HttpResponse
if (default_language is not None and if (default_language is not None and
default_language not in get_available_language_codes()): default_language not in get_available_language_codes()):
raise JsonableError(_("Invalid language '%s'" % (default_language,))) raise JsonableError(_("Invalid language '%s'" % (default_language,)))
if (timezone is not None and
timezone not in get_all_timezones()):
raise JsonableError(_("Invalid timezone '%s'" % (timezone,)))
result = {} # type: Dict[str, Any] result = {} # type: Dict[str, Any]
if (default_language is not None and if (default_language is not None and
user_profile.default_language != default_language): user_profile.default_language != default_language):
@ -185,6 +191,11 @@ def update_display_settings_backend(request, user_profile,
do_change_emoji_alt_code(user_profile, emoji_alt_code) do_change_emoji_alt_code(user_profile, emoji_alt_code)
result['emoji_alt_code'] = emoji_alt_code result['emoji_alt_code'] = emoji_alt_code
elif (timezone is not None and
user_profile.timezone != timezone):
do_change_timezone(user_profile, timezone)
result['timezone'] = timezone
return json_success(result) return json_success(result)
@has_request_variables @has_request_variables