mirror of https://github.com/zulip/zulip.git
Add a user-visible setting for 24-hour time display.
(imported from commit d934824fd6b72e64a455aac9ff4585b262145f02)
This commit is contained in:
parent
9734d1ab3f
commit
4d0f7c7ea4
|
@ -3,12 +3,8 @@ var feature_flags = (function () {
|
||||||
var exports = {};
|
var exports = {};
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
var special_24_hour_people= _.contains([],
|
|
||||||
page_params.email);
|
|
||||||
var og_zuliper_emails = [];
|
var og_zuliper_emails = [];
|
||||||
|
|
||||||
var iceland = page_params.domain === 'customer8.invalid';
|
|
||||||
|
|
||||||
var customer4_realms = [
|
var customer4_realms = [
|
||||||
'customer4.invalid',
|
'customer4.invalid',
|
||||||
'users.customer4.invalid'
|
'users.customer4.invalid'
|
||||||
|
@ -25,7 +21,6 @@ exports.collect_send_times = false;
|
||||||
// Permanent realm-specific stuff:
|
// Permanent realm-specific stuff:
|
||||||
exports.disable_message_editing = _.contains(['mit.edu'], page_params.domain);
|
exports.disable_message_editing = _.contains(['mit.edu'], page_params.domain);
|
||||||
exports.is_og_zulip_user = _.contains(og_zuliper_emails, page_params.email);
|
exports.is_og_zulip_user = _.contains(og_zuliper_emails, page_params.email);
|
||||||
exports.twenty_four_hour_time = special_24_hour_people || iceland;
|
|
||||||
|
|
||||||
exports.left_side_userlist = _.contains(['customer7.invalid'], page_params.domain);
|
exports.left_side_userlist = _.contains(['customer7.invalid'], page_params.domain);
|
||||||
exports.enable_new_user_app_alerts = ! _.contains(['employees.customer16.invalid'], page_params.domain);
|
exports.enable_new_user_app_alerts = ! _.contains(['employees.customer16.invalid'], page_params.domain);
|
||||||
|
|
|
@ -17,7 +17,7 @@ function MessageListView(list, table_name, collapse_messages) {
|
||||||
(function () {
|
(function () {
|
||||||
|
|
||||||
function stringify_time(time) {
|
function stringify_time(time) {
|
||||||
if (feature_flags.twenty_four_hour_time) {
|
if (page_params.twenty_four_hour_time) {
|
||||||
return time.toString('HH:mm');
|
return time.toString('HH:mm');
|
||||||
}
|
}
|
||||||
return time.toString('h:mm TT');
|
return time.toString('h:mm TT');
|
||||||
|
|
|
@ -180,6 +180,9 @@ function get_events_success(events) {
|
||||||
notifications.handle_global_notification_updates(event.notification_name,
|
notifications.handle_global_notification_updates(event.notification_name,
|
||||||
event.setting);
|
event.setting);
|
||||||
break;
|
break;
|
||||||
|
case 'update_display_settings':
|
||||||
|
page_params.twenty_four_hour_time = event.twenty_four_hour_time;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -151,6 +151,7 @@ exports.setup_page = function () {
|
||||||
$("#settings").html(settings_tab);
|
$("#settings").html(settings_tab);
|
||||||
$("#settings-status").hide();
|
$("#settings-status").hide();
|
||||||
$("#notify-settings-status").hide();
|
$("#notify-settings-status").hide();
|
||||||
|
$("#display-settings-status").hide();
|
||||||
$("#ui-settings-status").hide();
|
$("#ui-settings-status").hide();
|
||||||
|
|
||||||
alert_words_ui.set_up_alert_words();
|
alert_words_ui.set_up_alert_words();
|
||||||
|
@ -383,6 +384,41 @@ exports.setup_page = function () {
|
||||||
update_audible_notification_setting);
|
update_audible_notification_setting);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$("#twenty_four_hour_time").change(function () {
|
||||||
|
var time_checkbox = $("#twenty_four_hour_time").is(":checked");
|
||||||
|
var data = {};
|
||||||
|
data.twenty_four_hour_time = JSON.stringify(time_checkbox);
|
||||||
|
|
||||||
|
channel.patch({
|
||||||
|
url: '/json/time_setting',
|
||||||
|
data: data,
|
||||||
|
success: function (resp, statusText, xhr, form) {
|
||||||
|
var message = "Updated display settings!";
|
||||||
|
var result = $.parseJSON(xhr.responseText);
|
||||||
|
var display_settings_status = $('#display-settings-status').expectOne();
|
||||||
|
|
||||||
|
display_settings_status.removeClass(status_classes)
|
||||||
|
.addClass('alert-success')
|
||||||
|
.text(message).stop(true).fadeTo(0,1);
|
||||||
|
},
|
||||||
|
error: function (xhr, error_type, xhn) {
|
||||||
|
var response = "Error updating display settings";
|
||||||
|
var display_settings_status = $('#display-settings-status').expectOne();
|
||||||
|
|
||||||
|
if (xhr.status.toString().charAt(0) === "4") {
|
||||||
|
// Only display the error response for 4XX, where we've crafted
|
||||||
|
// a nice response.
|
||||||
|
response += ": " + $.parseJSON(xhr.responseText).msg;
|
||||||
|
}
|
||||||
|
display_settings_status.removeClass(status_classes)
|
||||||
|
.addClass('alert-error')
|
||||||
|
.text(response).stop(true).fadeTo(0,1);
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
$("#get_api_key_box").hide();
|
$("#get_api_key_box").hide();
|
||||||
$("#show_api_key_box").hide();
|
$("#show_api_key_box").hide();
|
||||||
$("#get_api_key_box form").ajaxForm({
|
$("#get_api_key_box form").ajaxForm({
|
||||||
|
|
|
@ -3299,7 +3299,7 @@ div.edit_bot {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
#settings #notify-settings-status,#ui-settings-status {
|
#settings #notify-settings-status,#ui-settings-status,#display-settings-status {
|
||||||
width: 80%;
|
width: 80%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
|
@ -3324,7 +3324,7 @@ div.edit_bot {
|
||||||
left: 20px;
|
left: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#settings .settings-section .notification-settings-form,.ui-settings-form {
|
#settings .settings-section .notification-settings-form,.ui-settings-form,.display-settings-form {
|
||||||
width: 400px;
|
width: 400px;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
}
|
}
|
||||||
|
@ -3343,6 +3343,7 @@ div.edit_bot {
|
||||||
}
|
}
|
||||||
|
|
||||||
#settings .settings-section .notification-settings-form .controls,
|
#settings .settings-section .notification-settings-form .controls,
|
||||||
|
#settings .settings-section .display-settings-form .controls,
|
||||||
#settings .settings-section .ui-settings-form .controls {
|
#settings .settings-section .ui-settings-form .controls {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
|
@ -3354,7 +3355,12 @@ div.edit_bot {
|
||||||
margin-right: 12px;
|
margin-right: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#settings .settings-section .display-settings-form .controls {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
#settings .settings-section .notification-settings-form .controls input[type='checkbox'],
|
#settings .settings-section .notification-settings-form .controls input[type='checkbox'],
|
||||||
|
#settings .settings-section .display-settings-form .controls input[type='checkbox'],
|
||||||
#settings .settings-section .ui-settings-form .controls input[type='checkbox'] {
|
#settings .settings-section .ui-settings-form .controls input[type='checkbox'] {
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
|
@ -3364,7 +3370,8 @@ div.edit_bot {
|
||||||
}
|
}
|
||||||
|
|
||||||
#settings .settings-section .notification-settings-form .control-label,
|
#settings .settings-section .notification-settings-form .control-label,
|
||||||
#settings .settings-section .ui-settings-form .control-label {
|
#settings .settings-section .ui-settings-form .control-label,
|
||||||
|
#settings .settings-section .display-settings-form .control-label {
|
||||||
float: none;
|
float: none;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
|
@ -3373,6 +3380,10 @@ div.edit_bot {
|
||||||
width: 240px;
|
width: 240px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#settings .settings-section .display-settings-form .control-label {
|
||||||
|
width: 360px;
|
||||||
|
}
|
||||||
|
|
||||||
#settings .settings-section .notification-settings-form .notification-submission,
|
#settings .settings-section .notification-settings-form .notification-submission,
|
||||||
#settings .settings-section .ui-settings-form .ui-submission {
|
#settings .settings-section .ui-settings-form .ui-submission {
|
||||||
margin-left: 140px;
|
margin-left: 140px;
|
||||||
|
@ -3477,6 +3488,7 @@ div.edit_bot {
|
||||||
#settings .settings-section .account-settings-form,
|
#settings .settings-section .account-settings-form,
|
||||||
#settings .settings-section .new-bot-form,
|
#settings .settings-section .new-bot-form,
|
||||||
#settings .settings-section .notification-settings-form,
|
#settings .settings-section .notification-settings-form,
|
||||||
|
#settings .settings-section .display-settings-form,
|
||||||
#settings .settings-section .edit-bot-form-box {
|
#settings .settings-section .edit-bot-form-box {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,6 +86,28 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div id="display-settings" class="settings-section">
|
||||||
|
<div class="settings-section-title"><i class="icon-vector-time settings-section-icon"></i>
|
||||||
|
Display Settings</div>
|
||||||
|
<div class="alert" id="display-settings-status"></div>
|
||||||
|
<div class="display-settings-form">
|
||||||
|
<div class="control-group">
|
||||||
|
<div class="controls">
|
||||||
|
<input type="checkbox" name="twenty_four_hour_time"
|
||||||
|
id="twenty_four_hour_time"
|
||||||
|
{{#if page_params.twenty_four_hour_time}}
|
||||||
|
checked="yes"
|
||||||
|
{{/if}} />
|
||||||
|
</div>
|
||||||
|
<label for="twenty_four_hour_time" class="control-label">
|
||||||
|
Display time in 24-hour format (17:00 instead of 5:00 PM)
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div id="notification-settings" class="settings-section">
|
<div id="notification-settings" class="settings-section">
|
||||||
<div class="settings-section-title"><i class="icon-vector-warning-sign settings-section-icon"></i>Notifications</div>
|
<div class="settings-section-title"><i class="icon-vector-warning-sign settings-section-icon"></i>Notifications</div>
|
||||||
|
|
|
@ -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.default_desktop_notifications = default_desktop_notifications
|
||||||
user_profile.save(update_fields=["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):
|
def set_default_streams(realm, stream_names):
|
||||||
DefaultStream.objects.filter(realm=realm).delete()
|
DefaultStream.objects.filter(realm=realm).delete()
|
||||||
for stream_name in stream_names:
|
for stream_name in stream_names:
|
||||||
|
@ -2359,6 +2369,9 @@ def fetch_initial_state_data(user_profile, event_types, queue_id):
|
||||||
if want('stream'):
|
if want('stream'):
|
||||||
state['streams'] = do_get_streams(user_profile)
|
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
|
return state
|
||||||
|
|
||||||
def apply_events(state, events, user_profile):
|
def apply_events(state, events, user_profile):
|
||||||
|
@ -2489,6 +2502,8 @@ def apply_events(state, events, user_profile):
|
||||||
state['muted_topics'] = event["muted_topics"]
|
state['muted_topics'] = event["muted_topics"]
|
||||||
elif event['type'] == "realm_filters":
|
elif event['type'] == "realm_filters":
|
||||||
state['realm_filters'] = event["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:
|
else:
|
||||||
raise ValueError("Unexpected event type %s" % (event['type'],))
|
raise ValueError("Unexpected event type %s" % (event['type'],))
|
||||||
|
|
||||||
|
|
|
@ -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']
|
|
@ -328,6 +328,9 @@ class UserProfile(AbstractBaseUser, PermissionsMixin):
|
||||||
enter_sends = models.NullBooleanField(default=True)
|
enter_sends = models.NullBooleanField(default=True)
|
||||||
autoscroll_forever = models.BooleanField(default=False)
|
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
|
# Hours to wait before sending another email to a user
|
||||||
EMAIL_REMINDER_WAITPERIOD = 24
|
EMAIL_REMINDER_WAITPERIOD = 24
|
||||||
# Minutes to wait before warning a bot owner that her bot sent a message
|
# Minutes to wait before warning a bot owner that her bot sent a message
|
||||||
|
|
|
@ -34,6 +34,7 @@ from zerver.lib.actions import (
|
||||||
do_set_realm_invite_by_admins_only,
|
do_set_realm_invite_by_admins_only,
|
||||||
do_update_message,
|
do_update_message,
|
||||||
do_update_pointer,
|
do_update_pointer,
|
||||||
|
do_change_twenty_four_hour_time,
|
||||||
fetch_initial_state_data,
|
fetch_initial_state_data,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -434,6 +435,21 @@ class EventsRegisterTest(AuthedTestCase):
|
||||||
error = schema_checker('events[0]', events[0])
|
error = schema_checker('events[0]', events[0])
|
||||||
self.assert_on_error(error)
|
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):
|
def test_realm_emoji_events(self):
|
||||||
schema_checker = check_dict([
|
schema_checker = check_dict([
|
||||||
('type', equals('realm_emoji')),
|
('type', equals('realm_emoji')),
|
||||||
|
@ -463,6 +479,7 @@ class EventsRegisterTest(AuthedTestCase):
|
||||||
error = schema_checker('events[0]', events[0])
|
error = schema_checker('events[0]', events[0])
|
||||||
self.assert_on_error(error)
|
self.assert_on_error(error)
|
||||||
|
|
||||||
|
|
||||||
def test_create_bot(self):
|
def test_create_bot(self):
|
||||||
bot_created_checker = check_dict([
|
bot_created_checker = check_dict([
|
||||||
('type', equals('realm_bot')),
|
('type', equals('realm_bot')),
|
||||||
|
|
|
@ -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_enable_stream_desktop_notifications, do_change_enable_stream_sounds, \
|
||||||
do_change_stream_description, do_get_streams, do_make_stream_private, \
|
do_change_stream_description, do_get_streams, do_make_stream_private, \
|
||||||
do_regenerate_api_key, do_remove_default_stream, do_update_pointer, \
|
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.create_user import random_api_key
|
||||||
from zerver.lib.push_notifications import num_push_devices_for_user
|
from zerver.lib.push_notifications import num_push_devices_for_user
|
||||||
|
@ -1071,6 +1071,7 @@ def home(request):
|
||||||
user_profile.enable_offline_email_notifications,
|
user_profile.enable_offline_email_notifications,
|
||||||
enable_offline_push_notifications =
|
enable_offline_push_notifications =
|
||||||
user_profile.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,
|
enable_digest_emails = user_profile.enable_digest_emails,
|
||||||
event_queue_id = register_ret['queue_id'],
|
event_queue_id = register_ret['queue_id'],
|
||||||
|
@ -1710,6 +1711,18 @@ def json_change_settings(request, user_profile,
|
||||||
|
|
||||||
return json_success(result)
|
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
|
@authenticated_json_post_view
|
||||||
@has_request_variables
|
@has_request_variables
|
||||||
def json_change_notify_settings(request, user_profile,
|
def json_change_notify_settings(request, user_profile,
|
||||||
|
|
|
@ -145,6 +145,7 @@ urlpatterns += patterns('zerver.views',
|
||||||
url(r'^json/set_alert_words$', 'json_set_alert_words'),
|
url(r'^json/set_alert_words$', 'json_set_alert_words'),
|
||||||
url(r'^json/set_muted_topics$', 'json_set_muted_topics'),
|
url(r'^json/set_muted_topics$', 'json_set_muted_topics'),
|
||||||
url(r'^json/set_avatar$', 'json_set_avatar'),
|
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
|
# This json format view is used by the LEGACY pre-REST API. It
|
||||||
# requires an API key.
|
# requires an API key.
|
||||||
|
|
Loading…
Reference in New Issue