Commit 5f73e3c3 by Bill DeRusha Committed by Bill DeRusha

Add social network to serializer

parent ac43a015
...@@ -17,8 +17,9 @@ from course_discovery.apps.api.fields import ImageField, StdImageSerializerField ...@@ -17,8 +17,9 @@ from course_discovery.apps.api.fields import ImageField, StdImageSerializerField
from course_discovery.apps.catalogs.models import Catalog from course_discovery.apps.catalogs.models import Catalog
from course_discovery.apps.course_metadata.choices import CourseRunStatus, ProgramStatus from course_discovery.apps.course_metadata.choices import CourseRunStatus, ProgramStatus
from course_discovery.apps.course_metadata.models import (FAQ, CorporateEndorsement, Course, CourseRun, Endorsement, from course_discovery.apps.course_metadata.models import (FAQ, CorporateEndorsement, Course, CourseRun, Endorsement,
Image, Organization, Person, PersonWork, Position, Image, Organization, Person, PersonSocialNetwork, PersonWork,
Prerequisite, Program, ProgramType, Seat, Subject, Video) Position, Prerequisite, Program, ProgramType, Seat, Subject,
Video)
from course_discovery.apps.course_metadata.search_indexes import CourseIndex, CourseRunIndex, ProgramIndex from course_discovery.apps.course_metadata.search_indexes import CourseIndex, CourseRunIndex, ProgramIndex
User = get_user_model() User = get_user_model()
...@@ -211,16 +212,19 @@ class PersonSerializer(serializers.ModelSerializer): ...@@ -211,16 +212,19 @@ class PersonSerializer(serializers.ModelSerializer):
position = PositionSerializer(required=False) position = PositionSerializer(required=False)
profile_image = StdImageSerializerField(required=False) profile_image = StdImageSerializerField(required=False)
works = serializers.SlugRelatedField(many=True, read_only=True, slug_field='value', source='person_works') works = serializers.SlugRelatedField(many=True, read_only=True, slug_field='value', source='person_works')
urls = serializers.SerializerMethodField()
@classmethod @classmethod
def prefetch_queryset(cls): def prefetch_queryset(cls):
return Person.objects.all().select_related('position__organization').prefetch_related('person_works') return Person.objects.all().select_related(
'position__organization'
).prefetch_related('person_works', 'person_networks')
class Meta(object): class Meta(object):
model = Person model = Person
fields = ( fields = (
'uuid', 'given_name', 'family_name', 'bio', 'profile_image_url', 'slug', 'position', 'profile_image', 'uuid', 'given_name', 'family_name', 'bio', 'profile_image_url', 'slug', 'position', 'profile_image',
'partner', 'works' 'partner', 'works', 'urls'
) )
extra_kwargs = { extra_kwargs = {
'partner': {'write_only': True} 'partner': {'write_only': True}
...@@ -229,20 +233,42 @@ class PersonSerializer(serializers.ModelSerializer): ...@@ -229,20 +233,42 @@ class PersonSerializer(serializers.ModelSerializer):
def validate(self, data): def validate(self, data):
validated_data = super(PersonSerializer, self).validate(data) validated_data = super(PersonSerializer, self).validate(data)
validated_data['works'] = self.initial_data.get('works', []) validated_data['works'] = self.initial_data.get('works', [])
validated_data['urls'] = self.initial_data.get('urls')
return validated_data return validated_data
def create(self, validated_data): def create(self, validated_data):
position_data = validated_data.pop('position') position_data = validated_data.pop('position')
works_data = validated_data.pop('works') works_data = validated_data.pop('works', [])
urls_data = validated_data.pop('urls', {})
person = Person.objects.create(**validated_data) person = Person.objects.create(**validated_data)
Position.objects.create(person=person, **position_data) Position.objects.create(person=person, **position_data)
person_social_networks = []
for url_type in [PersonSocialNetwork.FACEBOOK, PersonSocialNetwork.TWITTER, PersonSocialNetwork.BLOG]:
value = urls_data.get(url_type)
if value:
person_social_networks.append(PersonSocialNetwork(person=person, type=url_type, value=value))
PersonSocialNetwork.objects.bulk_create(person_social_networks)
person_works = [PersonWork(person=person, value=work_data) for work_data in works_data] person_works = [PersonWork(person=person, value=work_data) for work_data in works_data]
PersonWork.objects.bulk_create(person_works) PersonWork.objects.bulk_create(person_works)
return person return person
def get_social_network_url(self, url_type, obj):
social_network = obj.person_networks.filter(type=url_type).first()
if social_network:
return social_network.value
def get_urls(self, obj):
return {
PersonSocialNetwork.FACEBOOK: self.get_social_network_url(PersonSocialNetwork.FACEBOOK, obj),
PersonSocialNetwork.TWITTER: self.get_social_network_url(PersonSocialNetwork.TWITTER, obj),
PersonSocialNetwork.BLOG: self.get_social_network_url(PersonSocialNetwork.BLOG, obj),
}
class EndorsementSerializer(serializers.ModelSerializer): class EndorsementSerializer(serializers.ModelSerializer):
"""Serializer for the ``Endorsement`` model.""" """Serializer for the ``Endorsement`` model."""
......
...@@ -1117,6 +1117,11 @@ class PersonSerializerTests(TestCase): ...@@ -1117,6 +1117,11 @@ class PersonSerializerTests(TestCase):
'profile_image': image_field.to_representation(person.profile_image), 'profile_image': image_field.to_representation(person.profile_image),
'position': PositionSerializer(position).data, 'position': PositionSerializer(position).data,
'works': [work.value for work in person.person_works.all()], 'works': [work.value for work in person.person_works.all()],
'urls': {
'facebook': None,
'twitter': None,
'blog': None
},
'slug': person.slug, 'slug': person.slug,
} }
......
...@@ -39,6 +39,9 @@ class PersonViewSetTests(SerializationMixin, APITestCase): ...@@ -39,6 +39,9 @@ class PersonViewSetTests(SerializationMixin, APITestCase):
title = "Park Director" title = "Park Director"
organization_id = self.organization.id organization_id = self.organization.id
works = ["Delores", "Teddy", "Maive"] works = ["Delores", "Teddy", "Maive"]
facebook_url = 'http://www.facebook.com/hopkins'
twitter_url = 'http://www.twitter.com/hopkins'
blog_url = 'http://www.blog.com/hopkins'
data = { data = {
'data': json.dumps( 'data': json.dumps(
...@@ -50,7 +53,12 @@ class PersonViewSetTests(SerializationMixin, APITestCase): ...@@ -50,7 +53,12 @@ class PersonViewSetTests(SerializationMixin, APITestCase):
'title': title, 'title': title,
'organization': organization_id 'organization': organization_id
}, },
'works': works 'works': works,
'urls': {
'facebook': facebook_url,
'twitter': twitter_url,
'blog': blog_url
}
} }
) )
} }
...@@ -66,6 +74,10 @@ class PersonViewSetTests(SerializationMixin, APITestCase): ...@@ -66,6 +74,10 @@ class PersonViewSetTests(SerializationMixin, APITestCase):
self.assertEqual(person.position.title, title) self.assertEqual(person.position.title, title)
self.assertEqual(person.position.organization, self.organization) self.assertEqual(person.position.organization, self.organization)
self.assertEqual(sorted([work.value for work in person.person_works.all()]), sorted(works)) self.assertEqual(sorted([work.value for work in person.person_works.all()]), sorted(works))
self.assertEqual(
sorted([social.value for social in person.person_networks.all()]),
sorted([facebook_url, twitter_url, blog_url])
)
def test_create_without_authentication(self): def test_create_without_authentication(self):
""" Verify authentication is required when creating a person. """ """ Verify authentication is required when creating a person. """
......
...@@ -64,7 +64,7 @@ class ProgramViewSetTests(SerializationMixin, APITestCase): ...@@ -64,7 +64,7 @@ class ProgramViewSetTests(SerializationMixin, APITestCase):
def test_retrieve(self): def test_retrieve(self):
""" Verify the endpoint returns the details for a single program. """ """ Verify the endpoint returns the details for a single program. """
program = self.create_program() program = self.create_program()
with self.assertNumQueries(34): with self.assertNumQueries(42):
response = self.assert_retrieve_success(program) response = self.assert_retrieve_success(program)
assert response.data == self.serialize_program(program) assert response.data == self.serialize_program(program)
......
...@@ -25,6 +25,11 @@ class PersonWorkInline(admin.TabularInline): ...@@ -25,6 +25,11 @@ class PersonWorkInline(admin.TabularInline):
extra = 0 extra = 0
class PersonSocialNetworkInline(admin.TabularInline):
model = PersonSocialNetwork
extra = 0
class FaqsInline(admin.TabularInline): class FaqsInline(admin.TabularInline):
model = Program.faq.through model = Program.faq.through
exclude = ('sort_value',) exclude = ('sort_value',)
...@@ -197,7 +202,7 @@ class SubjectAdmin(admin.ModelAdmin): ...@@ -197,7 +202,7 @@ class SubjectAdmin(admin.ModelAdmin):
@admin.register(Person) @admin.register(Person)
class PersonAdmin(admin.ModelAdmin): class PersonAdmin(admin.ModelAdmin):
inlines = (PositionInline, PersonWorkInline,) inlines = (PositionInline, PersonWorkInline, PersonSocialNetworkInline)
list_display = ('uuid', 'family_name', 'given_name', 'slug',) list_display = ('uuid', 'family_name', 'given_name', 'slug',)
list_filter = ('partner',) list_filter = ('partner',)
ordering = ('family_name', 'given_name', 'uuid',) ordering = ('family_name', 'given_name', 'uuid',)
......
...@@ -7,14 +7,14 @@ msgid "" ...@@ -7,14 +7,14 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-02-13 14:47+0500\n" "POT-Creation-Date: 2017-02-13 07:55-0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Language: \n"
#: apps/api/filters.py #: apps/api/filters.py
#, python-brace-format #, python-brace-format
...@@ -916,11 +916,19 @@ msgid "Bio" ...@@ -916,11 +916,19 @@ msgid "Bio"
msgstr "" msgstr ""
#: templates/publisher/_add_instructor_popup.html #: templates/publisher/_add_instructor_popup.html
msgid "Social Links" msgid "Facebook URL"
msgstr "" msgstr ""
#: templates/publisher/_add_instructor_popup.html #: templates/publisher/_add_instructor_popup.html
msgid "optional - one per line" msgid "optional"
msgstr ""
#: templates/publisher/_add_instructor_popup.html
msgid "Twitter URL"
msgstr ""
#: templates/publisher/_add_instructor_popup.html
msgid "Blog URL"
msgstr "" msgstr ""
#: templates/publisher/_add_instructor_popup.html #: templates/publisher/_add_instructor_popup.html
...@@ -928,6 +936,10 @@ msgid "Major Works" ...@@ -928,6 +936,10 @@ msgid "Major Works"
msgstr "" msgstr ""
#: templates/publisher/_add_instructor_popup.html #: templates/publisher/_add_instructor_popup.html
msgid "optional - one per line"
msgstr ""
#: templates/publisher/_add_instructor_popup.html
msgid "Add Staff Member" msgid "Add Staff Member"
msgstr "" msgstr ""
......
...@@ -7,14 +7,14 @@ msgid "" ...@@ -7,14 +7,14 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-02-13 14:47+0500\n" "POT-Creation-Date: 2017-02-13 07:55-0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Language: \n"
#: static/js/catalogs-change-form.js #: static/js/catalogs-change-form.js
msgid "Preview" msgid "Preview"
......
...@@ -7,14 +7,14 @@ msgid "" ...@@ -7,14 +7,14 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-02-13 14:47+0500\n" "POT-Creation-Date: 2017-02-13 07:55-0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Language: \n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: apps/api/filters.py #: apps/api/filters.py
...@@ -1071,18 +1071,30 @@ msgid "Bio" ...@@ -1071,18 +1071,30 @@ msgid "Bio"
msgstr "Bïö Ⱡ'σяєм#" msgstr "Bïö Ⱡ'σяєм#"
#: templates/publisher/_add_instructor_popup.html #: templates/publisher/_add_instructor_popup.html
msgid "Social Links" msgid "Facebook URL"
msgstr "Söçïäl Lïnks Ⱡ'σяєм ιρѕυм ∂σłσя ѕ#" msgstr "Fäçéßöök ÛRL Ⱡ'σяєм ιρѕυм ∂σłσя ѕ#"
#: templates/publisher/_add_instructor_popup.html #: templates/publisher/_add_instructor_popup.html
msgid "optional - one per line" msgid "optional"
msgstr "öptïönäl - öné pér lïné Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σ#" msgstr "öptïönäl Ⱡ'σяєм ιρѕυм ∂#"
#: templates/publisher/_add_instructor_popup.html
msgid "Twitter URL"
msgstr "Twïttér ÛRL Ⱡ'σяєм ιρѕυм ∂σłσя #"
#: templates/publisher/_add_instructor_popup.html
msgid "Blog URL"
msgstr "Blög ÛRL Ⱡ'σяєм ιρѕυм ∂#"
#: templates/publisher/_add_instructor_popup.html #: templates/publisher/_add_instructor_popup.html
msgid "Major Works" msgid "Major Works"
msgstr "Mäjör Wörks Ⱡ'σяєм ιρѕυм ∂σłσя #" msgstr "Mäjör Wörks Ⱡ'σяєм ιρѕυм ∂σłσя #"
#: templates/publisher/_add_instructor_popup.html #: templates/publisher/_add_instructor_popup.html
msgid "optional - one per line"
msgstr "öptïönäl - öné pér lïné Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σ#"
#: templates/publisher/_add_instructor_popup.html
msgid "Add Staff Member" msgid "Add Staff Member"
msgstr "Àdd Stäff Mémßér Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αм#" msgstr "Àdd Stäff Mémßér Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αм#"
......
...@@ -7,14 +7,14 @@ msgid "" ...@@ -7,14 +7,14 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-02-13 14:47+0500\n" "POT-Creation-Date: 2017-02-13 07:55-0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Language: \n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: static/js/catalogs-change-form.js #: static/js/catalogs-change-form.js
......
...@@ -73,7 +73,12 @@ $(document).ready(function(){ ...@@ -73,7 +73,12 @@ $(document).ready(function(){
'title': $('#title').val(), 'title': $('#title').val(),
'organization': parseInt($('#id_organization').val()) 'organization': parseInt($('#id_organization').val())
}, },
'works': $('#majorWorks').val().split('\n') 'works': $('#majorWorks').val().split('\n'),
'urls': {
'facebook': $('#facebook').val(),
'twitter': $('#twitter').val(),
'blog': $('#blog').val()
}
} }
) )
}, },
...@@ -84,6 +89,9 @@ $(document).ready(function(){ ...@@ -84,6 +89,9 @@ $(document).ready(function(){
$('#bio').val(''); $('#bio').val('');
$('.select-image').attr('src', ''); $('.select-image').attr('src', '');
$('#majorWorks').val(''); $('#majorWorks').val('');
$('#facebook').val('');
$('#twitter').val('');
$('#blog').val('');
clearModalError(); clearModalError();
closeModal(e, $('#addInstructorModal')); closeModal(e, $('#addInstructorModal'));
}, },
......
...@@ -43,10 +43,20 @@ ...@@ -43,10 +43,20 @@
</label> </label>
<textarea class="field-textarea input-textarea textarea-medium textarea-block" id="bio" name="bio"></textarea> <textarea class="field-textarea input-textarea textarea-medium textarea-block" id="bio" name="bio"></textarea>
<label class="field-label" for="socialLinks">{% trans "Social Links" %}: <label class="field-label" for="facebook">{% trans "Facebook URL" %}:
<span class="optional">({% trans "optional - one per line" %} )</span> <span class="optional">* {% trans "optional" %}</span>
</label>
<input class="field-input input-text" type="text" id="facebook" name="facebook" />
<label class="field-label" for="twitter">{% trans "Twitter URL" %}:
<span class="optional">* {% trans "optional" %}</span>
</label>
<input class="field-input input-text" type="text" id="twitter" name="twitter" />
<label class="field-label" for="blog">{% trans "Blog URL" %}:
<span class="optional">* {% trans "optional" %}</span>
</label> </label>
<textarea class="field-textarea input-textarea textarea-medium textarea-block" id="socialLinks" name="social-links"></textarea> <input class="field-input input-text" type="text" id="blog" name="blog" />
<label class="field-label" for="majorWorks">{% trans "Major Works" %}: <label class="field-label" for="majorWorks">{% trans "Major Works" %}:
<span class="optional">({% trans "optional - one per line" %} )</span> <span class="optional">({% trans "optional - one per line" %} )</span>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment