mirror of https://github.com/zulip/zulip.git
drafts: Add support for toggling drafts synchronization.
With changes mostly to the API documentation by tabbott.
This commit is contained in:
parent
4d3b10d84d
commit
c00089ac28
|
@ -11,6 +11,15 @@ below features are supported.
|
||||||
|
|
||||||
## Changes in Zulip 5.0
|
## Changes in Zulip 5.0
|
||||||
|
|
||||||
|
**Feature level 87**
|
||||||
|
|
||||||
|
* [`PATCH /settings`](/api/update-settings): Added a new
|
||||||
|
`enable_drafts_synchronization` setting, which controls whether the
|
||||||
|
syncing drafts between different clients is enabled.
|
||||||
|
* [`GET /events`](/api/get-events), [`POST /register`](/api/register-queue):
|
||||||
|
Added new `enable_drafts_synchronization` setting under
|
||||||
|
`update_display_settings`.
|
||||||
|
|
||||||
**Feature level 86**
|
**Feature level 86**
|
||||||
|
|
||||||
* [`GET /events`](/api/get-events): Added `emoji_name`,
|
* [`GET /events`](/api/get-events): Added `emoji_name`,
|
||||||
|
|
|
@ -33,7 +33,7 @@ DESKTOP_WARNING_VERSION = "5.4.3"
|
||||||
# Changes should be accompanied by documentation explaining what the
|
# Changes should be accompanied by documentation explaining what the
|
||||||
# new level means in templates/zerver/api/changelog.md, as well as
|
# new level means in templates/zerver/api/changelog.md, as well as
|
||||||
# "**Changes**" entries in the endpoint's documentation in `zulip.yaml`.
|
# "**Changes**" entries in the endpoint's documentation in `zulip.yaml`.
|
||||||
API_FEATURE_LEVEL = 86
|
API_FEATURE_LEVEL = 87
|
||||||
|
|
||||||
# Bump the minor PROVISION_VERSION to indicate that folks should provision
|
# Bump the minor PROVISION_VERSION to indicate that folks should provision
|
||||||
# only when going from an old version of the code to a newer version. Bump
|
# only when going from an old version of the code to a newer version. Bump
|
||||||
|
|
|
@ -197,6 +197,7 @@ from zerver.models import (
|
||||||
CustomProfileFieldValue,
|
CustomProfileFieldValue,
|
||||||
DefaultStream,
|
DefaultStream,
|
||||||
DefaultStreamGroup,
|
DefaultStreamGroup,
|
||||||
|
Draft,
|
||||||
EmailChangeStatus,
|
EmailChangeStatus,
|
||||||
Message,
|
Message,
|
||||||
MultiuseInvite,
|
MultiuseInvite,
|
||||||
|
@ -5101,6 +5102,13 @@ def do_set_user_display_setting(
|
||||||
active_user_ids(user_profile.realm_id),
|
active_user_ids(user_profile.realm_id),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if setting_name == "enable_drafts_synchronization" and setting_value is False:
|
||||||
|
# Delete all of the drafts from the backend but don't send delete events
|
||||||
|
# for them since all that's happened is that we stopped syncing changes,
|
||||||
|
# not deleted every previously synced draft - to do that use the DELETE
|
||||||
|
# endpoint.
|
||||||
|
Draft.objects.filter(user_profile=user_profile).delete()
|
||||||
|
|
||||||
|
|
||||||
def lookup_default_stream_groups(
|
def lookup_default_stream_groups(
|
||||||
default_stream_group_names: List[str], realm: Realm
|
default_stream_group_names: List[str], realm: Realm
|
||||||
|
|
|
@ -1354,6 +1354,7 @@ class UserBaseSettings(models.Model):
|
||||||
demote_inactive_streams=int,
|
demote_inactive_streams=int,
|
||||||
dense_mode=bool,
|
dense_mode=bool,
|
||||||
emojiset=str,
|
emojiset=str,
|
||||||
|
enable_drafts_synchronization=bool,
|
||||||
enter_sends=bool,
|
enter_sends=bool,
|
||||||
fluid_layout_width=bool,
|
fluid_layout_width=bool,
|
||||||
high_contrast_mode=bool,
|
high_contrast_mode=bool,
|
||||||
|
|
|
@ -8830,6 +8830,17 @@ paths:
|
||||||
|
|
||||||
See [PATCH /settings](/api/update-settings) for details on
|
See [PATCH /settings](/api/update-settings) for details on
|
||||||
the meaning of this setting.
|
the meaning of this setting.
|
||||||
|
enable_drafts_synchronization:
|
||||||
|
type: boolean
|
||||||
|
description: |
|
||||||
|
Present if `update_display_settings` is present in `fetch_event_types`.
|
||||||
|
|
||||||
|
Whether drafts synchronization is enabled for the user.
|
||||||
|
|
||||||
|
See [PATCH /settings](/api/update-settings) for details on
|
||||||
|
the meaning of this setting.
|
||||||
|
|
||||||
|
**Changes**: New in Zulip 5.0 (feature level 87).
|
||||||
fluid_layout_width:
|
fluid_layout_width:
|
||||||
type: boolean
|
type: boolean
|
||||||
description: |
|
description: |
|
||||||
|
@ -10294,6 +10305,20 @@ paths:
|
||||||
- 2
|
- 2
|
||||||
- 3
|
- 3
|
||||||
example: 1
|
example: 1
|
||||||
|
- name: enable_drafts_synchronization
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
A boolean parameter to control whether synchronizing drafts is enabled for
|
||||||
|
the user. When synchronization is disabled, all drafts stored in the server
|
||||||
|
will be automatically deleted from the server.
|
||||||
|
|
||||||
|
This does not do anything (like sending events) to delete local copies of
|
||||||
|
drafts stored in clients.
|
||||||
|
|
||||||
|
**Changes**: New in Zulip 5.0 (feature level 87).
|
||||||
|
schema:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
- name: translate_emoticons
|
- name: translate_emoticons
|
||||||
in: query
|
in: query
|
||||||
description: |
|
description: |
|
||||||
|
|
|
@ -2299,3 +2299,21 @@ class SubscribeActionTest(BaseAction):
|
||||||
events[0]["streams"][0]["message_retention_days"],
|
events[0]["streams"][0]["message_retention_days"],
|
||||||
10,
|
10,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class DraftActionTest(BaseAction):
|
||||||
|
def do_enable_drafts_synchronization(self, user_profile: UserProfile) -> None:
|
||||||
|
do_set_user_display_setting(user_profile, "enable_drafts_synchronization", True)
|
||||||
|
|
||||||
|
def do_disable_drafts_synchronization(self, user_profile: UserProfile) -> None:
|
||||||
|
do_set_user_display_setting(user_profile, "enable_drafts_synchronization", False)
|
||||||
|
|
||||||
|
def test_enable_syncing_drafts(self) -> None:
|
||||||
|
self.do_disable_drafts_synchronization(self.user_profile)
|
||||||
|
action = lambda: self.do_enable_drafts_synchronization(self.user_profile)
|
||||||
|
self.verify_action(action)
|
||||||
|
|
||||||
|
def test_disable_syncing_drafts(self) -> None:
|
||||||
|
self.do_enable_drafts_synchronization(self.user_profile)
|
||||||
|
action = lambda: self.do_disable_drafts_synchronization(self.user_profile)
|
||||||
|
self.verify_action(action)
|
||||||
|
|
|
@ -70,6 +70,7 @@ class HomeTest(ZulipTestCase):
|
||||||
"emojiset_choices",
|
"emojiset_choices",
|
||||||
"enable_desktop_notifications",
|
"enable_desktop_notifications",
|
||||||
"enable_digest_emails",
|
"enable_digest_emails",
|
||||||
|
"enable_drafts_synchronization",
|
||||||
"enable_login_emails",
|
"enable_login_emails",
|
||||||
"enable_marketing_emails",
|
"enable_marketing_emails",
|
||||||
"enable_offline_email_notifications",
|
"enable_offline_email_notifications",
|
||||||
|
|
|
@ -11,7 +11,7 @@ from zerver.lib.rate_limiter import add_ratelimit_rule, remove_ratelimit_rule
|
||||||
from zerver.lib.test_classes import ZulipTestCase
|
from zerver.lib.test_classes import ZulipTestCase
|
||||||
from zerver.lib.test_helpers import get_test_image_file
|
from zerver.lib.test_helpers import get_test_image_file
|
||||||
from zerver.lib.users import get_all_api_keys
|
from zerver.lib.users import get_all_api_keys
|
||||||
from zerver.models import UserProfile, get_user_profile_by_api_key
|
from zerver.models import Draft, UserProfile, get_user_profile_by_api_key
|
||||||
|
|
||||||
|
|
||||||
class ChangeSettingsTest(ZulipTestCase):
|
class ChangeSettingsTest(ZulipTestCase):
|
||||||
|
@ -473,3 +473,52 @@ class UserChangesTest(ZulipTestCase):
|
||||||
|
|
||||||
for api_key in current_api_keys:
|
for api_key in current_api_keys:
|
||||||
self.assertEqual(get_user_profile_by_api_key(api_key).email, email)
|
self.assertEqual(get_user_profile_by_api_key(api_key).email, email)
|
||||||
|
|
||||||
|
|
||||||
|
class UserDraftSettingsTests(ZulipTestCase):
|
||||||
|
def test_enable_drafts_syncing(self) -> None:
|
||||||
|
hamlet = self.example_user("hamlet")
|
||||||
|
hamlet.enable_drafts_synchronization = False
|
||||||
|
hamlet.save()
|
||||||
|
payload = {"enable_drafts_synchronization": orjson.dumps(True).decode()}
|
||||||
|
resp = self.api_patch(hamlet, "/api/v1/settings", payload)
|
||||||
|
self.assert_json_success(resp)
|
||||||
|
hamlet = self.example_user("hamlet")
|
||||||
|
self.assertTrue(hamlet.enable_drafts_synchronization)
|
||||||
|
|
||||||
|
def test_disable_drafts_syncing(self) -> None:
|
||||||
|
aaron = self.example_user("aaron")
|
||||||
|
self.assertTrue(aaron.enable_drafts_synchronization)
|
||||||
|
|
||||||
|
initial_count = Draft.objects.count()
|
||||||
|
|
||||||
|
# Create some drafts. These should be deleted once aaron disables
|
||||||
|
# syncing drafts.
|
||||||
|
visible_stream_id = self.get_stream_id(self.get_streams(aaron)[0])
|
||||||
|
draft_dicts = [
|
||||||
|
{
|
||||||
|
"type": "stream",
|
||||||
|
"to": [visible_stream_id],
|
||||||
|
"topic": "thinking out loud",
|
||||||
|
"content": "What if pigs really could fly?",
|
||||||
|
"timestamp": 15954790199,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "private",
|
||||||
|
"to": [],
|
||||||
|
"topic": "",
|
||||||
|
"content": "What if made it possible to sync drafts in Zulip?",
|
||||||
|
"timestamp": 1595479020,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
payload = {"drafts": orjson.dumps(draft_dicts).decode()}
|
||||||
|
resp = self.api_post(aaron, "/api/v1/drafts", payload)
|
||||||
|
self.assert_json_success(resp)
|
||||||
|
self.assertEqual(Draft.objects.count() - initial_count, 2)
|
||||||
|
|
||||||
|
payload = {"enable_drafts_synchronization": orjson.dumps(False).decode()}
|
||||||
|
resp = self.api_patch(aaron, "/api/v1/settings", payload)
|
||||||
|
self.assert_json_success(resp)
|
||||||
|
aaron = self.example_user("aaron")
|
||||||
|
self.assertFalse(aaron.enable_drafts_synchronization)
|
||||||
|
self.assertEqual(Draft.objects.count() - initial_count, 0)
|
||||||
|
|
|
@ -123,6 +123,7 @@ def json_change_settings(
|
||||||
email_notifications_batching_period_seconds: Optional[int] = REQ(
|
email_notifications_batching_period_seconds: Optional[int] = REQ(
|
||||||
json_validator=check_int, default=None
|
json_validator=check_int, default=None
|
||||||
),
|
),
|
||||||
|
enable_drafts_synchronization: Optional[bool] = REQ(json_validator=check_bool, default=None),
|
||||||
enable_stream_desktop_notifications: Optional[bool] = REQ(
|
enable_stream_desktop_notifications: Optional[bool] = REQ(
|
||||||
json_validator=check_bool, default=None
|
json_validator=check_bool, default=None
|
||||||
),
|
),
|
||||||
|
|
Loading…
Reference in New Issue