Notifications
diff --git a/zerver/lib/actions.py b/zerver/lib/actions.py
index 7ab87e549a..9615ef0888 100644
--- a/zerver/lib/actions.py
+++ b/zerver/lib/actions.py
@@ -1717,6 +1717,16 @@ def do_change_default_desktop_notifications(user_profile, default_desktop_notifi
user_profile.default_desktop_notifications = default_desktop_notifications
user_profile.save(update_fields=["default_desktop_notifications"])
+def do_change_twenty_four_hour_time(user_profile, twenty_four_hour_time, log=True):
+ user_profile.twenty_four_hour_time = twenty_four_hour_time
+ user_profile.save(update_fields=["twenty_four_hour_time"])
+ event = {'type': 'update_display_settings',
+ 'user': user_profile.email,
+ 'setting': twenty_four_hour_time}
+ if log:
+ log_event(event)
+ send_event(event, [user_profile.id])
+
def set_default_streams(realm, stream_names):
DefaultStream.objects.filter(realm=realm).delete()
for stream_name in stream_names:
@@ -2359,6 +2369,9 @@ def fetch_initial_state_data(user_profile, event_types, queue_id):
if want('stream'):
state['streams'] = do_get_streams(user_profile)
+ if want('update_display_settings'):
+ state['twenty_four_hour_time'] = user_profile.twenty_four_hour_time
+
return state
def apply_events(state, events, user_profile):
@@ -2489,6 +2502,8 @@ def apply_events(state, events, user_profile):
state['muted_topics'] = event["muted_topics"]
elif event['type'] == "realm_filters":
state['realm_filters'] = event["realm_filters"]
+ elif event['type'] == "update_display_settings":
+ state['twenty_four_hour_time'] == event["twenty_four_hour_time"]
else:
raise ValueError("Unexpected event type %s" % (event['type'],))
diff --git a/zerver/migrations/0081_auto__add_field_userprofile_twenty_four_hour_time.py b/zerver/migrations/0081_auto__add_field_userprofile_twenty_four_hour_time.py
new file mode 100644
index 0000000000..ef7edc3618
--- /dev/null
+++ b/zerver/migrations/0081_auto__add_field_userprofile_twenty_four_hour_time.py
@@ -0,0 +1,275 @@
+# -*- coding: utf-8 -*-
+from south.utils import datetime_utils as datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+from django.conf import settings
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+ # Adding field 'UserProfile.twenty_four_hour_time'
+ db.add_column(u'zerver_userprofile', 'twenty_four_hour_time',
+ self.gf('django.db.models.fields.BooleanField')(default=False),
+ keep_default=True)
+ if settings.DEPLOYED and not settings.ENTERPRISE:
+ db.execute("UPDATE zerver_userprofile SET twenty_four_hour_time = TRUE WHERE realm_id IN " +
+ "(SELECT id FROM zerver_realm WHERE domain='customer8.invalid')")
+ db.execute("UPDATE zerver_userprofile SET twenty_four_hour_time = TRUE WHERE email IN ()")
+
+ def backwards(self, orm):
+ # Deleting field 'UserProfile.twenty_four_hour_time'
+ db.delete_column(u'zerver_userprofile', 'twenty_four_hour_time')
+
+
+ models = {
+ u'auth.group': {
+ 'Meta': {'object_name': 'Group'},
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+ },
+ u'auth.permission': {
+ 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ u'contenttypes.contenttype': {
+ 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ u'zerver.appledevicetoken': {
+ 'Meta': {'object_name': 'AppleDeviceToken'},
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'last_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'auto_now': 'True', 'blank': 'True'}),
+ 'token': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zerver.UserProfile']"})
+ },
+ u'zerver.client': {
+ 'Meta': {'object_name': 'Client'},
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30', 'db_index': 'True'})
+ },
+ u'zerver.defaultstream': {
+ 'Meta': {'unique_together': "(('realm', 'stream'),)", 'object_name': 'DefaultStream'},
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'realm': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zerver.Realm']"}),
+ 'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zerver.Stream']"})
+ },
+ u'zerver.huddle': {
+ 'Meta': {'object_name': 'Huddle'},
+ 'huddle_hash': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40', 'db_index': 'True'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
+ },
+ u'zerver.message': {
+ 'Meta': {'object_name': 'Message'},
+ 'content': ('django.db.models.fields.TextField', [], {}),
+ 'edit_history': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+ 'has_attachment': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}),
+ 'has_image': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}),
+ 'has_link': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'last_edit_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
+ 'pub_date': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
+ 'recipient': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zerver.Recipient']"}),
+ 'rendered_content': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+ 'rendered_content_version': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
+ 'sender': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zerver.UserProfile']"}),
+ 'sending_client': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zerver.Client']"}),
+ 'subject': ('django.db.models.fields.CharField', [], {'max_length': '60', 'db_index': 'True'})
+ },
+ u'zerver.mituser': {
+ 'Meta': {'object_name': 'MitUser'},
+ 'email': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'status': ('django.db.models.fields.IntegerField', [], {'default': '0'})
+ },
+ u'zerver.preregistrationuser': {
+ 'Meta': {'object_name': 'PreregistrationUser'},
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'invited_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+ 'realm': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zerver.Realm']", 'null': 'True'}),
+ 'referred_by': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zerver.UserProfile']", 'null': 'True'}),
+ 'status': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'streams': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['zerver.Stream']", 'null': 'True', 'symmetrical': 'False'})
+ },
+ u'zerver.pushdevicetoken': {
+ 'Meta': {'object_name': 'PushDeviceToken'},
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'ios_app_id': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+ 'kind': ('django.db.models.fields.PositiveSmallIntegerField', [], {}),
+ 'last_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'auto_now': 'True', 'blank': 'True'}),
+ 'token': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '4096'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zerver.UserProfile']"})
+ },
+ u'zerver.realm': {
+ 'Meta': {'object_name': 'Realm'},
+ 'date_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'deactivated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'domain': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40', 'db_index': 'True'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'invite_by_admins_only': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'invite_required': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'mandatory_topics': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True'}),
+ 'name_changes_disabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'notifications_stream': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': u"orm['zerver.Stream']"}),
+ 'restricted_to_domain': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'show_digest_email': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
+ },
+ u'zerver.realmalias': {
+ 'Meta': {'object_name': 'RealmAlias'},
+ 'domain': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80', 'db_index': 'True'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'realm': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zerver.Realm']", 'null': 'True'})
+ },
+ u'zerver.realmemoji': {
+ 'Meta': {'unique_together': "(('realm', 'name'),)", 'object_name': 'RealmEmoji'},
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'img_url': ('django.db.models.fields.TextField', [], {}),
+ 'name': ('django.db.models.fields.TextField', [], {}),
+ 'realm': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zerver.Realm']"})
+ },
+ u'zerver.realmfilter': {
+ 'Meta': {'unique_together': "(('realm', 'pattern'),)", 'object_name': 'RealmFilter'},
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'pattern': ('django.db.models.fields.TextField', [], {}),
+ 'realm': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zerver.Realm']"}),
+ 'url_format_string': ('django.db.models.fields.TextField', [], {})
+ },
+ u'zerver.recipient': {
+ 'Meta': {'unique_together': "(('type', 'type_id'),)", 'object_name': 'Recipient'},
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'type': ('django.db.models.fields.PositiveSmallIntegerField', [], {'db_index': 'True'}),
+ 'type_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'})
+ },
+ u'zerver.referral': {
+ 'Meta': {'object_name': 'Referral'},
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'timestamp': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'user_profile': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zerver.UserProfile']"})
+ },
+ u'zerver.scheduledjob': {
+ 'Meta': {'object_name': 'ScheduledJob'},
+ 'data': ('django.db.models.fields.TextField', [], {}),
+ 'filter_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
+ 'filter_string': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'scheduled_timestamp': ('django.db.models.fields.DateTimeField', [], {}),
+ 'type': ('django.db.models.fields.PositiveSmallIntegerField', [], {})
+ },
+ u'zerver.stream': {
+ 'Meta': {'unique_together': "(('name', 'realm'),)", 'object_name': 'Stream'},
+ 'date_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'deactivated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'description': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}),
+ 'email_token': ('django.db.models.fields.CharField', [], {'default': "'db559172cf87493869af805bd51da2d4'", 'max_length': '32'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'invite_only': ('django.db.models.fields.NullBooleanField', [], {'default': 'False', 'null': 'True', 'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '60', 'db_index': 'True'}),
+ 'realm': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zerver.Realm']"})
+ },
+ u'zerver.streamcolor': {
+ 'Meta': {'object_name': 'StreamColor'},
+ 'color': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'subscription': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zerver.Subscription']"})
+ },
+ u'zerver.subscription': {
+ 'Meta': {'unique_together': "(('user_profile', 'recipient'),)", 'object_name': 'Subscription'},
+ 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'audible_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'color': ('django.db.models.fields.CharField', [], {'default': "'#c2c2c2'", 'max_length': '10'}),
+ 'desktop_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'in_home_view': ('django.db.models.fields.NullBooleanField', [], {'default': 'True', 'null': 'True', 'blank': 'True'}),
+ 'notifications': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'recipient': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zerver.Recipient']"}),
+ 'user_profile': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zerver.UserProfile']"})
+ },
+ u'zerver.useractivity': {
+ 'Meta': {'unique_together': "(('user_profile', 'client', 'query'),)", 'object_name': 'UserActivity'},
+ 'client': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zerver.Client']"}),
+ 'count': ('django.db.models.fields.IntegerField', [], {}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'last_visit': ('django.db.models.fields.DateTimeField', [], {}),
+ 'query': ('django.db.models.fields.CharField', [], {'max_length': '50', 'db_index': 'True'}),
+ 'user_profile': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zerver.UserProfile']"})
+ },
+ u'zerver.useractivityinterval': {
+ 'Meta': {'object_name': 'UserActivityInterval'},
+ 'end': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'start': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
+ 'user_profile': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zerver.UserProfile']"})
+ },
+ u'zerver.usermessage': {
+ 'Meta': {'unique_together': "(('user_profile', 'message'),)", 'object_name': 'UserMessage'},
+ 'flags': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zerver.Message']"}),
+ 'user_profile': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zerver.UserProfile']"})
+ },
+ u'zerver.userpresence': {
+ 'Meta': {'unique_together': "(('user_profile', 'client'),)", 'object_name': 'UserPresence'},
+ 'client': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zerver.Client']"}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'status': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '1'}),
+ 'timestamp': ('django.db.models.fields.DateTimeField', [], {}),
+ 'user_profile': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zerver.UserProfile']"})
+ },
+ u'zerver.userprofile': {
+ 'Meta': {'object_name': 'UserProfile'},
+ 'alert_words': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+ 'api_key': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'autoscroll_forever': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'avatar_source': ('django.db.models.fields.CharField', [], {'default': "'G'", 'max_length': '1'}),
+ 'bot_owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zerver.UserProfile']", 'null': 'True', 'on_delete': 'models.SET_NULL'}),
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'default_all_public_streams': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'default_desktop_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'default_events_register_stream': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'null': 'True', 'to': u"orm['zerver.Stream']"}),
+ 'default_sending_stream': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'null': 'True', 'to': u"orm['zerver.Stream']"}),
+ 'email': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75', 'db_index': 'True'}),
+ 'enable_desktop_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'enable_digest_emails': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'enable_offline_email_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'enable_offline_push_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'enable_sounds': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'enable_stream_desktop_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'enable_stream_sounds': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'enter_sends': ('django.db.models.fields.NullBooleanField', [], {'default': 'True', 'null': 'True', 'blank': 'True'}),
+ 'full_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'invites_granted': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'invites_used': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'is_bot': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'is_mirror_dummy': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_pointer_updater': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
+ 'last_reminder': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'null': 'True'}),
+ 'muted_topics': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+ 'onboarding_steps': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'pointer': ('django.db.models.fields.IntegerField', [], {}),
+ 'rate_limits': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
+ 'realm': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zerver.Realm']"}),
+ 'short_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'tutorial_status': ('django.db.models.fields.CharField', [], {'default': "'W'", 'max_length': '1'}),
+ 'twenty_four_hour_time': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"})
+ }
+ }
+
+ complete_apps = ['zerver']
diff --git a/zerver/models.py b/zerver/models.py
index 605862b47c..af8d698090 100644
--- a/zerver/models.py
+++ b/zerver/models.py
@@ -328,6 +328,9 @@ class UserProfile(AbstractBaseUser, PermissionsMixin):
enter_sends = models.NullBooleanField(default=True)
autoscroll_forever = models.BooleanField(default=False)
+ # display settings
+ twenty_four_hour_time = models.BooleanField(default=False)
+
# Hours to wait before sending another email to a user
EMAIL_REMINDER_WAITPERIOD = 24
# Minutes to wait before warning a bot owner that her bot sent a message
diff --git a/zerver/test_events.py b/zerver/test_events.py
index 5a4982d5d7..cc35047a3b 100644
--- a/zerver/test_events.py
+++ b/zerver/test_events.py
@@ -34,6 +34,7 @@ from zerver.lib.actions import (
do_set_realm_invite_by_admins_only,
do_update_message,
do_update_pointer,
+ do_change_twenty_four_hour_time,
fetch_initial_state_data,
)
@@ -434,6 +435,21 @@ class EventsRegisterTest(AuthedTestCase):
error = schema_checker('events[0]', events[0])
self.assert_on_error(error)
+ def test_change_twenty_four_hour_time(self):
+ schema_checker = check_dict([
+ ('type', equals('update_display_settings')),
+ ('op', equals('update')),
+ ('person', check_dict([
+ ('email', check_string),
+ ('twenty_four_hour_time', check_bool),
+ ])),
+ ])
+ # The first False is probably a noop, then we get transitions in both directions.
+ for twenty_four_hour_time in [False, True, False]:
+ events = self.do_test(lambda: do_change_twenty_four_hour_time(self.user_profile, twenty_four_hour_time))
+ error = schema_checker('events[0]', events[0])
+ self.assert_on_error(error)
+
def test_realm_emoji_events(self):
schema_checker = check_dict([
('type', equals('realm_emoji')),
@@ -463,6 +479,7 @@ class EventsRegisterTest(AuthedTestCase):
error = schema_checker('events[0]', events[0])
self.assert_on_error(error)
+
def test_create_bot(self):
bot_created_checker = check_dict([
('type', equals('realm_bot')),
diff --git a/zerver/views/__init__.py b/zerver/views/__init__.py
index c3ed332737..0c9e41d62a 100644
--- a/zerver/views/__init__.py
+++ b/zerver/views/__init__.py
@@ -46,7 +46,7 @@ from zerver.lib.actions import bulk_remove_subscriptions, do_change_password, \
do_change_enable_stream_desktop_notifications, do_change_enable_stream_sounds, \
do_change_stream_description, do_get_streams, do_make_stream_private, \
do_regenerate_api_key, do_remove_default_stream, do_update_pointer, \
- do_change_avatar_source
+ do_change_avatar_source, do_change_twenty_four_hour_time
from zerver.lib.create_user import random_api_key
from zerver.lib.push_notifications import num_push_devices_for_user
@@ -1071,6 +1071,7 @@ def home(request):
user_profile.enable_offline_email_notifications,
enable_offline_push_notifications =
user_profile.enable_offline_push_notifications,
+ twenty_four_hour_time = register_ret['twenty_four_hour_time'],
enable_digest_emails = user_profile.enable_digest_emails,
event_queue_id = register_ret['queue_id'],
@@ -1710,6 +1711,18 @@ def json_change_settings(request, user_profile,
return json_success(result)
+@authenticated_json_post_view
+@has_request_variables
+def json_time_setting(request, user_profile, twenty_four_hour_time=REQ(validator=check_bool,default=None)):
+ result = {}
+ if twenty_four_hour_time is not None and \
+ user_profile.twenty_four_hour_time != twenty_four_hour_time:
+ do_change_twenty_four_hour_time(user_profile, twenty_four_hour_time)
+
+ result['twenty_four_hour_time'] = twenty_four_hour_time
+
+ return json_success(result)
+
@authenticated_json_post_view
@has_request_variables
def json_change_notify_settings(request, user_profile,
diff --git a/zproject/urls.py b/zproject/urls.py
index 46adfd6aca..52bb270206 100644
--- a/zproject/urls.py
+++ b/zproject/urls.py
@@ -145,6 +145,7 @@ urlpatterns += patterns('zerver.views',
url(r'^json/set_alert_words$', 'json_set_alert_words'),
url(r'^json/set_muted_topics$', 'json_set_muted_topics'),
url(r'^json/set_avatar$', 'json_set_avatar'),
+ url(r'^json/time_setting$', 'json_time_setting'),
# This json format view is used by the LEGACY pre-REST API. It
# requires an API key.