profile: Add hint attribute to custom profile fields.

This is the model for #8876.
This commit is contained in:
Umair Khan 2018-03-31 10:30:24 +05:00 committed by Tim Abbott
parent 00ffa808da
commit 0420b89468
7 changed files with 103 additions and 14 deletions

View File

@ -4527,8 +4527,10 @@ def notify_realm_custom_profile_fields(realm: Realm, operation: str) -> None:
fields=[f.as_dict() for f in fields])
send_event(event, active_user_ids(realm.id))
def try_add_realm_custom_profile_field(realm: Realm, name: Text, field_type: int) -> CustomProfileField:
def try_add_realm_custom_profile_field(realm: Realm, name: Text, field_type: int,
hint: Text='') -> CustomProfileField:
field = CustomProfileField(realm=realm, name=name, field_type=field_type)
field.hint = hint
field.save()
notify_realm_custom_profile_fields(realm, 'add')
return field
@ -4542,9 +4544,10 @@ def do_remove_realm_custom_profile_field(realm: Realm, field: CustomProfileField
notify_realm_custom_profile_fields(realm, 'delete')
def try_update_realm_custom_profile_field(realm: Realm, field: CustomProfileField,
name: Text) -> None:
name: Text, hint: Text='') -> None:
field.name = name
field.save(update_fields=['name'])
field.hint = hint
field.save(update_fields=['name', 'hint'])
notify_realm_custom_profile_fields(realm, 'update')
def do_update_user_custom_profile_data(user_profile: UserProfile,

View File

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.11 on 2018-04-06 04:10
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('zerver', '0155_change_default_realm_description'),
]
operations = [
migrations.AddField(
model_name='customprofilefield',
name='hint',
field=models.CharField(default='', max_length=80, null=True),
),
]

View File

@ -740,10 +740,10 @@ class UserProfile(AbstractBaseUser, PermissionsMixin):
unique_together = (('realm', 'email'),)
@property
def profile_data(self) -> List[Dict[str, Union[int, float, Text]]]:
def profile_data(self) -> List[Dict[str, Union[int, float, Optional[Text]]]]:
values = CustomProfileFieldValue.objects.filter(user_profile=self)
user_data = {v.field_id: v.value for v in values}
data = [] # type: List[Dict[str, Union[int, float, Text]]]
data = [] # type: List[Dict[str, Union[int, float, Optional[Text]]]]
for field in custom_profile_fields_for_realm(self.realm_id):
value = user_data.get(field.id, None)
field_type = field.field_type
@ -751,7 +751,7 @@ class UserProfile(AbstractBaseUser, PermissionsMixin):
converter = field.FIELD_CONVERTERS[field_type]
value = converter(value)
field_data = {} # type: Dict[str, Union[int, float, Text]]
field_data = {} # type: Dict[str, Union[int, float, Optional[Text]]]
for k, v in field.as_dict().items():
field_data[k] = v
field_data['value'] = value
@ -1873,8 +1873,11 @@ class UserHotspot(models.Model):
unique_together = ("user", "hotspot")
class CustomProfileField(models.Model):
HINT_MAX_LENGTH = 80
realm = models.ForeignKey(Realm, on_delete=CASCADE) # type: Realm
name = models.CharField(max_length=100) # type: Text
hint = models.CharField(max_length=HINT_MAX_LENGTH, default='', null=True) # type: Optional[Text]
SHORT_TEXT = 1
LONG_TEXT = 2
@ -1895,11 +1898,12 @@ class CustomProfileField(models.Model):
class Meta:
unique_together = ('realm', 'name')
def as_dict(self) -> Dict[str, Union[int, Text]]:
def as_dict(self) -> Dict[str, Union[int, Optional[Text]]]:
return {
'id': self.id,
'name': self.name,
'type': self.field_type,
'hint': self.hint,
}
def __str__(self) -> str:

View File

@ -37,6 +37,14 @@ class CustomProfileFieldTest(ZulipTestCase):
self.assert_json_error(result, u'Invalid field type.')
data["name"] = "Phone"
data["hint"] = "*" * 81
data["field_type"] = CustomProfileField.SHORT_TEXT
result = self.client_post("/json/realm/profile_fields", info=data)
msg = "hint is longer than 80."
self.assert_json_error(result, msg)
data["name"] = "Phone"
data["hint"] = "Contact number"
data["field_type"] = CustomProfileField.SHORT_TEXT
result = self.client_post("/json/realm/profile_fields", info=data)
self.assert_json_success(result)
@ -90,10 +98,31 @@ class CustomProfileFieldTest(ZulipTestCase):
info={'name': 'New phone number',
'field_type': CustomProfileField.SHORT_TEXT})
self.assert_json_success(result)
field = CustomProfileField.objects.get(id=field.id, realm=realm)
self.assertEqual(CustomProfileField.objects.count(), 3)
self.assertEqual(field.name, 'New phone number')
self.assertIs(field.hint, '')
self.assertEqual(field.field_type, CustomProfileField.SHORT_TEXT)
result = self.client_patch(
"/json/realm/profile_fields/{}".format(field.id),
info={'name': 'New phone number',
'hint': '*' * 81,
'field_type': CustomProfileField.SHORT_TEXT})
msg = "hint is longer than 80."
self.assert_json_error(result, msg)
result = self.client_patch(
"/json/realm/profile_fields/{}".format(field.id),
info={'name': 'New phone number',
'hint': 'New contact number',
'field_type': CustomProfileField.SHORT_TEXT})
self.assert_json_success(result)
field = CustomProfileField.objects.get(id=field.id, realm=realm)
self.assertEqual(CustomProfileField.objects.count(), 3)
self.assertEqual(field.name, 'New phone number')
self.assertEqual(field.hint, 'New contact number')
self.assertEqual(field.field_type, CustomProfileField.SHORT_TEXT)
def test_update_is_aware_of_uniqueness(self) -> None:

View File

@ -18,6 +18,7 @@ from zerver.models import (
)
from zerver.lib.actions import (
try_update_realm_custom_profile_field,
bulk_add_subscriptions,
bulk_remove_subscriptions,
check_add_realm_emoji,
@ -915,6 +916,7 @@ class EventsRegisterTest(ZulipTestCase):
('id', check_int),
('type', check_int),
('name', check_string),
('hint', check_string),
]))),
])
@ -926,6 +928,20 @@ class EventsRegisterTest(ZulipTestCase):
error = schema_checker('events[0]', events[0])
self.assert_on_error(error)
realm = self.user_profile.realm
field = realm.customprofilefield_set.get(realm=realm, name='Biography')
name = field.name
hint = 'Biography of the user'
try_update_realm_custom_profile_field(realm, field, name, hint=hint)
events = self.do_test(
lambda: notify_realm_custom_profile_fields(
self.user_profile.realm, 'add'),
state_change_expected=False,
)
error = schema_checker('events[0]', events[0])
self.assert_on_error(error)
def test_presence_events(self) -> None:
schema_checker = self.check_events_dict([
('type', equals('presence')),

View File

@ -1,5 +1,5 @@
from typing import Text, Union, List, Dict
from typing import Text, Union, List, Dict, Optional
import logging
from django.core.exceptions import ValidationError
@ -14,7 +14,7 @@ from zerver.lib.actions import (try_add_realm_custom_profile_field,
try_update_realm_custom_profile_field,
do_update_user_custom_profile_data)
from zerver.lib.response import json_success, json_error
from zerver.lib.validator import check_dict, check_list, check_int
from zerver.lib.validator import check_dict, check_list, check_int, check_capped_string
from zerver.models import (custom_profile_fields_for_realm, UserProfile,
CustomProfileField, custom_profile_fields_for_realm)
@ -23,14 +23,21 @@ def list_realm_custom_profile_fields(request: HttpRequest, user_profile: UserPro
fields = custom_profile_fields_for_realm(user_profile.realm_id)
return json_success({'custom_fields': [f.as_dict() for f in fields]})
hint_validator = check_capped_string(CustomProfileField.HINT_MAX_LENGTH)
@require_realm_admin
@has_request_variables
def create_realm_custom_profile_field(request: HttpRequest,
user_profile: UserProfile, name: Text=REQ(),
hint: Text=REQ(default=''),
field_type: int=REQ(validator=check_int)) -> HttpResponse:
if not name.strip():
return json_error(_("Name cannot be blank."))
error = hint_validator('hint', hint)
if error:
return json_error(error)
if field_type not in CustomProfileField.FIELD_VALIDATORS:
return json_error(_("Invalid field type."))
@ -39,6 +46,7 @@ def create_realm_custom_profile_field(request: HttpRequest,
realm=user_profile.realm,
name=name,
field_type=field_type,
hint=hint,
)
return json_success({'id': field.id})
except IntegrityError:
@ -59,10 +67,16 @@ def delete_realm_custom_profile_field(request: HttpRequest, user_profile: UserPr
@require_realm_admin
@has_request_variables
def update_realm_custom_profile_field(request: HttpRequest, user_profile: UserProfile,
field_id: int, name: Text=REQ()) -> HttpResponse:
field_id: int, name: Text=REQ(),
hint: Text=REQ(default='')
) -> HttpResponse:
if not name.strip():
return json_error(_("Name cannot be blank."))
error = hint_validator('hint', hint)
if error:
return json_error(error, data={'field': 'hint'})
realm = user_profile.realm
try:
field = CustomProfileField.objects.get(realm=realm, id=field_id)
@ -70,7 +84,7 @@ def update_realm_custom_profile_field(request: HttpRequest, user_profile: UserPr
return json_error(_('Field id {id} not found.').format(id=field_id))
try:
try_update_realm_custom_profile_field(realm, field, name)
try_update_realm_custom_profile_field(realm, field, name, hint=hint)
except IntegrityError:
return json_error(_('A field with that name already exists.'))
return json_success()

View File

@ -253,11 +253,14 @@ class Command(BaseCommand):
# Create custom profile field data
phone_number = try_add_realm_custom_profile_field(zulip_realm, "Phone number",
CustomProfileField.SHORT_TEXT)
CustomProfileField.SHORT_TEXT,
hint='')
biography = try_add_realm_custom_profile_field(zulip_realm, "Biography",
CustomProfileField.LONG_TEXT)
CustomProfileField.LONG_TEXT,
hint='What are you known for?')
favorite_food = try_add_realm_custom_profile_field(zulip_realm, "Favorite food",
CustomProfileField.SHORT_TEXT)
CustomProfileField.SHORT_TEXT,
hint="Or drink, if you'd prefer")
# Fill in values for Iago and Hamlet
hamlet = get_user("hamlet@zulip.com", zulip_realm)