From 1f98c4f4ce2c5c0dc5b998d892191b416adca449 Mon Sep 17 00:00:00 2001 From: Jason Michalski Date: Wed, 22 Jan 2014 14:20:10 -0500 Subject: [PATCH] Add support for updating the stream description The stream description can now be updated, but the UI is not yet updated on success. (imported from commit f45e0a9d5138d828ae98d6d49645ab3ddc966704) --- static/js/subs.js | 25 +++++++++++++++++++++++++ zerver/lib/actions.py | 14 ++++++++++++++ zerver/tests.py | 39 +++++++++++++++++++++++++++++++++++++-- zerver/views/__init__.py | 14 ++++++++++++-- zproject/urls.py | 1 + 5 files changed, 89 insertions(+), 4 deletions(-) diff --git a/static/js/subs.js b/static/js/subs.js index cb9e09e962..6bbf4f9304 100644 --- a/static/js/subs.js +++ b/static/js/subs.js @@ -831,6 +831,31 @@ $(function () { }); }); + $('#subscriptions_table').on('submit', '.change-stream-description form', function (e) { + e.preventDefault(); + var $form = $(e.target); + + var $sub_row = $(e.target).closest('.subscription_row'); + var stream_name = $sub_row.find('.subscription_name').text(); + var description = $sub_row.find('input[name="description"]').val(); + + $('#subscription_status').hide(); + + channel.patch({ + url: '/json/streams/' + stream_name, + data: { + 'description': JSON.stringify(description) + }, + success: function () { + // The event from the server will update the rest of the UI + ui.report_success("The stream description has been updated!", $("#subscriptions-status")); + }, + error: function (xhr) { + ui.report_error("Error updating the stream description", xhr, $("#subscriptions-status")); + } + }); + }); + function redraw_privacy_related_stuff(sub_row, sub) { var html; diff --git a/zerver/lib/actions.py b/zerver/lib/actions.py index a869f2c408..a67ce44053 100644 --- a/zerver/lib/actions.py +++ b/zerver/lib/actions.py @@ -852,6 +852,7 @@ def notify_subscriptions_added(user_profile, sub_pairs, stream_emails, no_log=Fa color=subscription.color, email_address=encode_email_address(stream), notifications=subscription.notifications, + description=stream.description, subscribers=stream_emails(stream)) for (subscription, stream) in sub_pairs] notice = dict(event=dict(type="subscriptions", op="add", @@ -1265,6 +1266,19 @@ def do_rename_stream(realm, old_name, new_name, log=True): # email forwarding address to display the correctly-escaped new name. return {"email_address": encode_email_address(stream)} +def do_change_stream_description(realm, stream_name, new_description): + stream = get_stream(stream_name, realm) + stream.description = new_description + stream.save(update_fields=['description']) + + notice = dict(event=dict(type='stream', op='update', + property='description', name=stream_name, + value=new_description), + users=active_user_ids(realm)) + + tornado_callbacks.send_notification(notice) + return {} + def do_create_realm(domain, name, restricted_to_domain=True): realm = get_realm(domain) created = not realm diff --git a/zerver/tests.py b/zerver/tests.py index 2498415e8f..13c9b45faf 100644 --- a/zerver/tests.py +++ b/zerver/tests.py @@ -23,7 +23,7 @@ from zerver.lib.actions import check_send_message, gather_subscriptions, \ do_add_realm_emoji, do_remove_realm_emoji, check_message, do_create_user, \ set_default_streams, get_emails_from_user_ids, one_click_unsubscribe_link, \ do_deactivate_user, do_reactivate_user, enqueue_welcome_emails, do_change_is_admin, \ - do_rename_stream + do_rename_stream, do_change_stream_description from zerver.lib.rate_limiter import add_ratelimit_rule, remove_ratelimit_rule from zerver.lib import bugdown from zerver.lib import cache @@ -466,7 +466,7 @@ class AuthedTestCase(TestCase): Successful POSTs return a 200 and JSON of the form {"result": "success", "msg": ""}. """ - self.assertEqual(result.status_code, 200) + self.assertEqual(result.status_code, 200, result) json = ujson.loads(result.content) self.assertEqual(json.get("result"), "success") # We have a msg key for consistency with errors, but it typically has an @@ -638,6 +638,38 @@ class StreamAdminTest(AuthedTestCase): result = self.client.post('/json/rename_stream?old_name=stream_name1&new_name=stream_name2') self.assert_json_error(result, 'Must be a realm administrator') + def test_change_stream_description(self): + email = 'hamlet@zulip.com' + self.login(email) + user_profile = get_user_profile_by_email(email) + realm = user_profile.realm + stream, _ = create_stream_if_needed(realm, 'stream_name1') + do_add_subscription(user_profile, stream, no_log=True) + do_change_is_admin(user_profile, True) + + result = self.client_patch('/json/streams/stream_name1', + {'description': ujson.dumps('Test description')}) + self.assert_json_success(result) + + stream = Stream.objects.get( + name='stream_name1', + realm=realm, + ) + self.assertEqual('Test description', stream.description) + + def test_change_stream_description_requires_realm_admin(self): + email = 'hamlet@zulip.com' + self.login(email) + user_profile = get_user_profile_by_email(email) + realm = user_profile.realm + stream, _ = create_stream_if_needed(realm, 'stream_name1') + do_add_subscription(user_profile, stream, no_log=True) + do_change_is_admin(user_profile, False) + + result = self.client_patch('/json/streams/stream_name1', + {'description': ujson.dumps('Test description')}) + self.assert_json_error(result, 'Must be a realm administrator') + class TestCrossRealmPMs(AuthedTestCase): def create_user(self, email): username, domain = email.split('@') @@ -3666,6 +3698,9 @@ class EventsRegisterTest(AuthedTestCase): matcher=lambda a, b: self.match_except(a, b, "unsubscribed")) self.do_test(lambda: self.subscribe_to_stream("hamlet@zulip.com", "test_stream"), matcher=lambda a, b: self.match_with_reorder(a, b, "subscriptions")) + self.do_test(lambda: do_change_stream_description(get_realm('zulip.com'), 'test_stream', + 'new description'), + matcher=lambda a, b: self.match_with_reorder(a, b, "subscriptions")) from zerver.lib.event_queue import EventQueue class EventQueueTest(TestCase): diff --git a/zerver/views/__init__.py b/zerver/views/__init__.py index 48f70c930c..d9630bd4a3 100644 --- a/zerver/views/__init__.py +++ b/zerver/views/__init__.py @@ -37,7 +37,8 @@ from zerver.lib.actions import bulk_remove_subscriptions, do_change_password, \ do_set_muted_topics, do_rename_stream, clear_followup_emails_queue, \ notify_for_streams_by_default, do_change_enable_offline_push_notifications, \ do_deactivate_stream, do_change_autoscroll_forever, do_make_stream_public, \ - do_make_stream_private, do_change_default_desktop_notifications + do_make_stream_private, do_change_default_desktop_notifications, \ + do_change_stream_description from zerver.lib.create_user import random_api_key from zerver.lib.push_notifications import num_push_devices_for_user from zerver.forms import RegistrationForm, HomepageForm, ToSForm, \ @@ -55,7 +56,8 @@ from zerver.decorator import require_post, \ authenticated_api_view, authenticated_json_post_view, \ has_request_variables, authenticated_json_view, \ to_non_negative_int, json_to_dict, json_to_list, json_to_bool, \ - JsonableError, get_user_profile_by_email, REQ, require_realm_admin + JsonableError, get_user_profile_by_email, REQ, require_realm_admin, \ + RequestVariableConversionError from zerver.lib.avatar import avatar_url, get_avatar_url from zerver.lib.upload import upload_message_image_through_web_client, upload_avatar_image, \ get_signed_upload_url @@ -1106,6 +1108,14 @@ def json_make_stream_public(request, user_profile, stream_name=REQ): def json_make_stream_private(request, user_profile, stream_name=REQ): return json_success(do_make_stream_private(user_profile.realm, stream_name)) +@require_realm_admin +@has_request_variables +def update_stream_backend(request, user_profile, stream_name, + description=REQ(validator=check_string, default=None)): + if description is not None: + do_change_stream_description(user_profile.realm, stream_name, description) + return json_success({}) + def list_subscriptions_backend(request, user_profile): return json_success({"subscriptions": gather_subscriptions(user_profile)[0]}) diff --git a/zproject/urls.py b/zproject/urls.py index 7e6694a3e4..8d998b3f8d 100644 --- a/zproject/urls.py +++ b/zproject/urls.py @@ -177,6 +177,7 @@ v1_api_and_json_patterns = patterns('zerver.views', url(r'^streams/(?P.*)$', 'rest_dispatch', {'HEAD': 'stream_exists_backend', 'GET': 'stream_exists_backend', + 'PATCH': 'update_stream_backend', 'DELETE': 'deactivate_stream_backend'}), url(r'^users$', 'rest_dispatch', {'GET': 'get_members_backend',