retention-period: Add retention period to front-end admin organization settings.

- Add message retention period field to organization settings form.
- Add css for retention period field.
- Add convertor to not negative int or to None.
- Add retention period setting processing to back-end.
- Fix tests.

Modified by tabbott to hide the setting, since it doesn't work yet.
The goal of merging this setting code now is to avoid unnecessary
merge conflicts in the future.

Part of #106.
This commit is contained in:
K.Kanakhin
2016-11-30 15:42:58 +06:00
committed by Tim Abbott
parent 6a884acff5
commit 234a1f8e61
14 changed files with 73 additions and 5 deletions

View File

@@ -374,6 +374,10 @@ exports.populate_auth_methods = function (auth_methods) {
loading.destroy_indicator($('#admin_page_auth_methods_loading_indicator')); loading.destroy_indicator($('#admin_page_auth_methods_loading_indicator'));
}; };
exports.update_message_retention_days = function () {
$("#id_realm_message_retention_days").val(page_params.message_retention_days);
};
function _setup_page() { function _setup_page() {
var options = { var options = {
realm_name: page_params.realm_name, realm_name: page_params.realm_name,
@@ -393,6 +397,7 @@ function _setup_page() {
realm_allow_message_editing: page_params.realm_allow_message_editing, realm_allow_message_editing: page_params.realm_allow_message_editing,
realm_message_content_edit_limit_minutes: realm_message_content_edit_limit_minutes:
Math.ceil(page_params.realm_message_content_edit_limit_seconds / 60), Math.ceil(page_params.realm_message_content_edit_limit_seconds / 60),
realm_message_retention_days: page_params.realm_message_retention_days,
language_list: page_params.language_list, language_list: page_params.language_list,
realm_default_language: page_params.realm_default_language, realm_default_language: page_params.realm_default_language,
realm_waiting_period_threshold: page_params.realm_waiting_period_threshold, realm_waiting_period_threshold: page_params.realm_waiting_period_threshold,
@@ -669,6 +674,7 @@ function _setup_page() {
var new_add_emoji_by_admins_only = $("#id_realm_add_emoji_by_admins_only").prop("checked"); var new_add_emoji_by_admins_only = $("#id_realm_add_emoji_by_admins_only").prop("checked");
var new_allow_message_editing = $("#id_realm_allow_message_editing").prop("checked"); var new_allow_message_editing = $("#id_realm_allow_message_editing").prop("checked");
var new_message_content_edit_limit_minutes = $("#id_realm_message_content_edit_limit_minutes").val(); var new_message_content_edit_limit_minutes = $("#id_realm_message_content_edit_limit_minutes").val();
var new_message_retention_days = $("#id_realm_message_retention_days").val();
var new_default_language = $("#id_realm_default_language").val(); var new_default_language = $("#id_realm_default_language").val();
var new_waiting_period_threshold = $("#id_realm_waiting_period_threshold").val(); var new_waiting_period_threshold = $("#id_realm_waiting_period_threshold").val();
var new_auth_methods = {}; var new_auth_methods = {};
@@ -687,6 +693,10 @@ function _setup_page() {
new_message_content_edit_limit_minutes = 10; new_message_content_edit_limit_minutes = 10;
} }
} }
if (parseInt(new_message_retention_days, 10).toString() !==
new_message_retention_days && new_message_retention_days !== "") {
new_message_retention_days = "";
}
var url = "/json/realm"; var url = "/json/realm";
var data = { var data = {
@@ -705,6 +715,7 @@ function _setup_page() {
allow_message_editing: JSON.stringify(new_allow_message_editing), allow_message_editing: JSON.stringify(new_allow_message_editing),
message_content_edit_limit_seconds: message_content_edit_limit_seconds:
JSON.stringify(parseInt(new_message_content_edit_limit_minutes, 10) * 60), JSON.stringify(parseInt(new_message_content_edit_limit_minutes, 10) * 60),
message_retention_days: new_message_retention_days !== "" ? JSON.stringify(parseInt(new_message_retention_days, 10)) : null,
default_language: JSON.stringify(new_default_language), default_language: JSON.stringify(new_default_language),
waiting_period_threshold: JSON.stringify(parseInt(new_waiting_period_threshold, 10)), waiting_period_threshold: JSON.stringify(parseInt(new_waiting_period_threshold, 10)),
}; };

View File

@@ -81,6 +81,9 @@ function dispatch_normal_event(event) {
page_params.add_emoji_by_admins_only = event.value; page_params.add_emoji_by_admins_only = event.value;
} else if (event.op === 'update' && event.property === 'restricted_to_domain') { } else if (event.op === 'update' && event.property === 'restricted_to_domain') {
page_params.realm_restricted_to_domain = event.value; page_params.realm_restricted_to_domain = event.value;
} else if (event.op === 'update' && event.property === 'message_retention_days') {
page_params.message_retention_days = event.value;
admin.update_message_retention_days();
} else if (event.op === 'update_dict' && event.property === 'default') { } else if (event.op === 'update_dict' && event.property === 'default') {
$.each(event.data, function (key, value) { $.each(event.data, function (key, value) {
page_params['realm_' + key] = value; page_params['realm_' + key] = value;

View File

@@ -421,6 +421,11 @@ input[type=checkbox].inline-block {
text-align: right; text-align: right;
} }
.admin-realm-message-retention-days {
width: 5ch;
text-align: right;
}
#account-settings-status { #account-settings-status {
text-align: center; text-align: center;
width: 50%; width: 50%;

View File

@@ -147,6 +147,19 @@
value="{{ realm_message_content_edit_limit_minutes }}" value="{{ realm_message_content_edit_limit_minutes }}"
{{#unless realm_allow_message_editing}}disabled="disabled"{{/unless}} /> {{#unless realm_allow_message_editing}}disabled="disabled"{{/unless}} />
</div> </div>
{{#if false}}
<div class="input-group">
<label for="realm_message_retention_days"
id="id_realm_message_retention_days_label"
title="{{t 'If empty, messages are not moved to archive.' }}">
{{t 'Retention period for messages in days (empty for disable)' }}
</label>
<input type="text" id="id_realm_message_retention_days"
name="realm_message_retention_days"
class="admin-realm-message-retention-days"
value="{{ realm_message_retention_days }}"/>
</div>
{{/if}}
<div class="input-group"> <div class="input-group">
<label for="realm_default_language">{{t "Default language" }}:</label> <label for="realm_default_language">{{t "Default language" }}:</label>
<select name="realm_default_language" id="id_realm_default_language"> <select name="realm_default_language" id="id_realm_default_language">

View File

@@ -536,6 +536,14 @@ def to_non_negative_int(s):
raise ValueError("argument is negative") raise ValueError("argument is negative")
return x return x
def to_not_negative_int_or_none(s):
# type: (Text) -> Optional[int]
if s:
return to_non_negative_int(s)
return None
def flexible_boolean(boolean): def flexible_boolean(boolean):
# type: (Text) -> bool # type: (Text) -> bool
"""Returns True for any of "1", "true", or "True". Returns False otherwise.""" """Returns True for any of "1", "true", or "True". Returns False otherwise."""

View File

@@ -474,7 +474,6 @@ def do_set_realm_message_editing(realm, allow_message_editing, message_content_e
) )
send_event(event, active_user_ids(realm)) send_event(event, active_user_ids(realm))
def do_deactivate_realm(realm): def do_deactivate_realm(realm):
# type: (Realm) -> None # type: (Realm) -> None
""" """

View File

@@ -104,6 +104,7 @@ def fetch_initial_state_data(user_profile, event_types, queue_id,
state['realm_add_emoji_by_admins_only'] = user_profile.realm.add_emoji_by_admins_only state['realm_add_emoji_by_admins_only'] = user_profile.realm.add_emoji_by_admins_only
state['realm_allow_message_editing'] = user_profile.realm.allow_message_editing state['realm_allow_message_editing'] = user_profile.realm.allow_message_editing
state['realm_message_content_edit_limit_seconds'] = user_profile.realm.message_content_edit_limit_seconds state['realm_message_content_edit_limit_seconds'] = user_profile.realm.message_content_edit_limit_seconds
state['realm_message_retention_days'] = user_profile.realm.message_retention_days
state['realm_default_language'] = user_profile.realm.default_language state['realm_default_language'] = user_profile.realm.default_language
state['realm_waiting_period_threshold'] = user_profile.realm.waiting_period_threshold state['realm_waiting_period_threshold'] = user_profile.realm.waiting_period_threshold
state['realm_icon_url'] = realm_icon_url(user_profile.realm) state['realm_icon_url'] = realm_icon_url(user_profile.realm)

View File

@@ -155,6 +155,7 @@ class Realm(ModelReprMixin, models.Model):
invite_by_admins_only=bool, invite_by_admins_only=bool,
inline_image_preview=bool, inline_image_preview=bool,
inline_url_embed_preview=bool, inline_url_embed_preview=bool,
message_retention_days=int,
name=Text, name=Text,
name_changes_disabled=bool, name_changes_disabled=bool,
restricted_to_domain=bool, restricted_to_domain=bool,

View File

@@ -72,7 +72,8 @@ from zerver.lib.actions import (
do_add_realm_alias, do_add_realm_alias,
do_change_realm_alias, do_change_realm_alias,
do_remove_realm_alias, do_remove_realm_alias,
do_change_icon_source) do_change_icon_source,
)
from zerver.lib.events import ( from zerver.lib.events import (
apply_events, apply_events,
fetch_initial_state_data, fetch_initial_state_data,
@@ -761,6 +762,19 @@ class EventsRegisterTest(ZulipTestCase):
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_message_retention_days(self):
# type: () -> None
schema_checker = check_dict([
('type', equals('realm')),
('op', equals('update')),
('property', equals('message_retention_days')),
('value', check_int),
])
events = self.do_test(
lambda: do_set_realm_property(self.user_profile.realm, "message_retention_days", 30))
error = schema_checker('events[0]', events[0])
self.assert_on_error(error)
def test_change_realm_add_emoji_by_admins_only(self): def test_change_realm_add_emoji_by_admins_only(self):
# type: () -> None # type: () -> None
schema_checker = check_dict([ schema_checker = check_dict([

View File

@@ -110,6 +110,7 @@ class HomeTest(ZulipTestCase):
"realm_invite_by_admins_only", "realm_invite_by_admins_only",
"realm_invite_required", "realm_invite_required",
"realm_message_content_edit_limit_seconds", "realm_message_content_edit_limit_seconds",
"realm_message_retention_days",
"realm_name", "realm_name",
"realm_name_changes_disabled", "realm_name_changes_disabled",
"realm_presence_disabled", "realm_presence_disabled",

View File

@@ -212,6 +212,13 @@ class RealmTest(ZulipTestCase):
realm = update_with_api(waiting_period_threshold=10) realm = update_with_api(waiting_period_threshold=10)
self.assertEqual(realm.waiting_period_threshold, 10) self.assertEqual(realm.waiting_period_threshold, 10)
# retention_period
set_up_db('message_retention_days', 10)
realm = update_with_api(message_retention_days=20)
self.assertEqual(realm.message_retention_days, 20)
realm = update_with_api(message_retention_days=10)
self.assertEqual(realm.message_retention_days, 10)
def test_admin_restrictions_for_changing_realm_name(self): def test_admin_restrictions_for_changing_realm_name(self):
# type: () -> None # type: () -> None
new_name = 'Mice will play while the cat is away' new_name = 'Mice will play while the cat is away'

0
zerver/tests/tests.py Normal file
View File

View File

@@ -305,6 +305,7 @@ def home_real(request):
'realm_inline_url_embed_preview', 'realm_inline_url_embed_preview',
'realm_invite_required', 'realm_invite_required',
'realm_message_content_edit_limit_seconds', 'realm_message_content_edit_limit_seconds',
'realm_message_retention_days',
'realm_name', 'realm_name',
'realm_description', 'realm_description',
'realm_name_changes_disabled', 'realm_name_changes_disabled',

View File

@@ -4,7 +4,7 @@ from typing import Any, Dict, Optional
from django.http import HttpRequest, HttpResponse from django.http import HttpRequest, HttpResponse
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from zerver.decorator import require_realm_admin, to_non_negative_int from zerver.decorator import require_realm_admin, to_non_negative_int, to_not_negative_int_or_none
from zerver.lib.actions import ( from zerver.lib.actions import (
do_set_realm_message_editing, do_set_realm_message_editing,
do_set_realm_authentication_methods, do_set_realm_authentication_methods,
@@ -34,8 +34,9 @@ def update_realm(request, user_profile, name=REQ(validator=check_string, default
message_content_edit_limit_seconds=REQ(converter=to_non_negative_int, default=None), message_content_edit_limit_seconds=REQ(converter=to_non_negative_int, default=None),
default_language=REQ(validator=check_string, default=None), default_language=REQ(validator=check_string, default=None),
waiting_period_threshold=REQ(converter=to_non_negative_int, default=None), waiting_period_threshold=REQ(converter=to_non_negative_int, default=None),
authentication_methods=REQ(validator=check_dict([]), default=None)): authentication_methods=REQ(validator=check_dict([]), default=None),
# type: (HttpRequest, UserProfile, Optional[str], Optional[str], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[int], Optional[str], Optional[int], Optional[dict]) -> HttpResponse message_retention_days=REQ(converter=to_not_negative_int_or_none, default=None)):
# type: (HttpRequest, UserProfile, Optional[str], Optional[str], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[int], Optional[str], Optional[int], Optional[dict], Optional[int]) -> HttpResponse
# Validation for default_language # Validation for default_language
if default_language is not None and default_language not in get_available_language_codes(): if default_language is not None and default_language not in get_available_language_codes():
raise JsonableError(_("Invalid language '%s'" % (default_language,))) raise JsonableError(_("Invalid language '%s'" % (default_language,)))
@@ -99,4 +100,7 @@ def update_realm(request, user_profile, name=REQ(validator=check_string, default
if waiting_period_threshold is not None and realm.waiting_period_threshold != waiting_period_threshold: if waiting_period_threshold is not None and realm.waiting_period_threshold != waiting_period_threshold:
do_set_realm_property(realm, 'waiting_period_threshold', waiting_period_threshold) do_set_realm_property(realm, 'waiting_period_threshold', waiting_period_threshold)
data['waiting_period_threshold'] = waiting_period_threshold data['waiting_period_threshold'] = waiting_period_threshold
if realm.message_retention_days != message_retention_days:
do_set_realm_property(realm, 'message_retention_days', message_retention_days)
data['message_retention_days'] = message_retention_days
return json_success(data) return json_success(data)